int utf32_char_width(int c) {
  if (c == 0)
    return 0;
  if (c >= 0x1100 &&
      (c <= 0x115f ||
       (c >= 0x2e80 && c <= 0xa4cf && (c & ~0x0011) != 0x300a && c != 0x303f) ||
       (c >= 0xac00 && c <= 0xd7a3) || (c >= 0xdf00 && c <= 0xdfff) ||
       (c >= 0xf900 && c <= 0xfaff) || (c >= 0xfe30 && c <= 0xfe6f) ||
       (c >= 0xff00 && c <= 0xff5f) || (c >= 0xffe0 && c <= 0xffe6) ||
       (c >= 0x20000 && c <= 0x2ffff)))
    return 2;
  return 1;
}


x86 assembly (clang, -O0):
<utf32_char_width>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x8(%rbp)
cmpl   $0x0,-0x8(%rbp)
jne    111d <utf32_char_width+0x1d>
movl   $0x0,-0x4(%rbp)
jmp    1238 <utf32_char_width+0x138>
cmpl   $0x1100,-0x8(%rbp)
jl     1231 <utf32_char_width+0x131>
cmpl   $0x115f,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0x2e80,-0x8(%rbp)
jl     116f <utf32_char_width+0x6f>
cmpl   $0xa4cf,-0x8(%rbp)
jg     116f <utf32_char_width+0x6f>
mov    -0x8(%rbp),%eax
and    $0xffffffee,%eax
cmp    $0x300a,%eax
je     116f <utf32_char_width+0x6f>
cmpl   $0x303f,-0x8(%rbp)
jne    1225 <utf32_char_width+0x125>
cmpl   $0xac00,-0x8(%rbp)
jl     1189 <utf32_char_width+0x89>
cmpl   $0xd7a3,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0xdf00,-0x8(%rbp)
jl     11a3 <utf32_char_width+0xa3>
cmpl   $0xdfff,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0xf900,-0x8(%rbp)
jl     11bd <utf32_char_width+0xbd>
cmpl   $0xfaff,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0xfe30,-0x8(%rbp)
jl     11d7 <utf32_char_width+0xd7>
cmpl   $0xfe6f,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0xff00,-0x8(%rbp)
jl     11f1 <utf32_char_width+0xf1>
cmpl   $0xff5f,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0xffe0,-0x8(%rbp)
jl     120b <utf32_char_width+0x10b>
cmpl   $0xffe6,-0x8(%rbp)
jle    1225 <utf32_char_width+0x125>
cmpl   $0x20000,-0x8(%rbp)
jl     1231 <utf32_char_width+0x131>
cmpl   $0x2ffff,-0x8(%rbp)
jg     1231 <utf32_char_width+0x131>
movl   $0x2,-0x4(%rbp)
jmp    1238 <utf32_char_width+0x138>
movl   $0x1,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<utf32_char_width>:
test   %edi,%edi
je     1141 <utf32_char_width+0x41>
cmp    $0x1100,%edi
jl     119c <utf32_char_width+0x9c>
mov    $0x2,%eax
cmp    $0x1160,%edi
jb     1140 <utf32_char_width+0x40>
lea    -0x2e80(%rdi),%ecx
cmp    $0x764f,%ecx
ja     1144 <utf32_char_width+0x44>
cmp    $0x303f,%edi
je     1152 <utf32_char_width+0x52>
mov    %edi,%ecx
and    $0xffffffee,%ecx
cmp    $0x300a,%ecx
je     1152 <utf32_char_width+0x52>
ret
xor    %eax,%eax
ret
lea    -0xac00(%rdi),%ecx
cmp    $0x2ba4,%ecx
jb     1140 <utf32_char_width+0x40>
movd   %edi,%xmm0
pshufd $0x0,%xmm0,%xmm0
paddd  0xe9d(%rip),%xmm0
pxor   0xea5(%rip),%xmm0
movdqa 0xead(%rip),%xmm1
pcmpgtd %xmm0,%xmm1
movmskps %xmm1,%ecx
test   %ecx,%ecx
jne    1140 <utf32_char_width+0x40>
mov    %edi,%ecx
and    $0xffff0000,%ecx
cmp    $0x20000,%ecx
je     1140 <utf32_char_width+0x40>
and    $0xffffff00,%edi
cmp    $0xdf00,%edi
je     1140 <utf32_char_width+0x40>
mov    $0x1,%eax
ret

LLVM IR (-O0):
define i32 @utf32_char_width(i32 %0) {
%2 = alloca i32
%3 = alloca i32
store i32 %0, i32* %3
%4 = load i32, i32* %3
%5 = icmp eq i32 %4, 0
br i1 %5, label %6, label %7
6: ; preds = %1
store i32 0, i32* %2
br label %70
7: ; preds = %1
%8 = load i32, i32* %3
%9 = icmp sge i32 %8, 4352
br i1 %9, label %10, label %69
10: ; preds = %7
%11 = load i32, i32* %3
%12 = icmp sle i32 %11, 4447
br i1 %12, label %68, label %13
13: ; preds = %10
%14 = load i32, i32* %3
%15 = icmp sge i32 %14, 11904
br i1 %15, label %16, label %26
16: ; preds = %13
%17 = load i32, i32* %3
%18 = icmp sle i32 %17, 42191
br i1 %18, label %19, label %26
19: ; preds = %16
%20 = load i32, i32* %3
%21 = and i32 %20, -18
%22 = icmp ne i32 %21, 12298
br i1 %22, label %23, label %26
23: ; preds = %19
%24 = load i32, i32* %3
%25 = icmp ne i32 %24, 12351
br i1 %25, label %68, label %26
26: ; preds = %23, %19, %16, %13
%27 = load i32, i32* %3
%28 = icmp sge i32 %27, 44032
br i1 %28, label %29, label %32
29: ; preds = %26
%30 = load i32, i32* %3
%31 = icmp sle i32 %30, 55203
br i1 %31, label %68, label %32
32: ; preds = %29, %26
%33 = load i32, i32* %3
%34 = icmp sge i32 %33, 57088
br i1 %34, label %35, label %38
35: ; preds = %32
%36 = load i32, i32* %3
%37 = icmp sle i32 %36, 57343
br i1 %37, label %68, label %38
38: ; preds = %35, %32
%39 = load i32, i32* %3
%40 = icmp sge i32 %39, 63744
br i1 %40, label %41, label %44
41: ; preds = %38
%42 = load i32, i32* %3
%43 = icmp sle i32 %42, 64255
br i1 %43, label %68, label %44
44: ; preds = %41, %38
%45 = load i32, i32* %3
%46 = icmp sge i32 %45, 65072
br i1 %46, label %47, label %50
47: ; preds = %44
%48 = load i32, i32* %3
%49 = icmp sle i32 %48, 65135
br i1 %49, label %68, label %50
50: ; preds = %47, %44
%51 = load i32, i32* %3
%52 = icmp sge i32 %51, 65280
br i1 %52, label %53, label %56
53: ; preds = %50
%54 = load i32, i32* %3
%55 = icmp sle i32 %54, 65375
br i1 %55, label %68, label %56
56: ; preds = %53, %50
%57 = load i32, i32* %3
%58 = icmp sge i32 %57, 65504
br i1 %58, label %59, label %62
59: ; preds = %56
%60 = load i32, i32* %3
%61 = icmp sle i32 %60, 65510
br i1 %61, label %68, label %62
62: ; preds = %59, %56
%63 = load i32, i32* %3
%64 = icmp sge i32 %63, 131072
br i1 %64, label %65, label %69
65: ; preds = %62
%66 = load i32, i32* %3
%67 = icmp sle i32 %66, 196607
br i1 %67, label %68, label %69
68: ; preds = %65, %59, %53, %47, %41, %35, %29, %23, %10
store i32 2, i32* %2
br label %70
69: ; preds = %65, %62, %7
store i32 1, i32* %2
br label %70
70: ; preds = %69, %68, %6
%71 = load i32, i32* %2
ret i32 %71
}

LLVM IR (-O2):
define i32 @utf32_char_width(i32 %0) {
%2 = icmp eq i32 %0, 0
br i1 %2, label %32, label %3
3: ; preds = %1
%4 = icmp sgt i32 %0, 4351
br i1 %4, label %5, label %31
5: ; preds = %3
%6 = icmp ult i32 %0, 4448
br i1 %6, label %32, label %7
7: ; preds = %5
%8 = add nsw i32 %0, -11904
%9 = icmp ult i32 %8, 30288
br i1 %9, label %10, label %15
10: ; preds = %7
%11 = and i32 %0, -18
%12 = icmp ne i32 %11, 12298
%13 = icmp ne i32 %0, 12351
%14 = and i1 %13, %12
br i1 %14, label %32, label %18
15: ; preds = %7
%16 = add nsw i32 %0, -44032
%17 = icmp ult i32 %16, 11172
br i1 %17, label %32, label %18
18: ; preds = %10, %15
%19 = and i32 %0, -256
%20 = icmp eq i32 %19, 57088
%21 = insertelement <4 x i32> poison, i32 %0, i64 0
%22 = shufflevector <4 x i32> %21, <4 x i32> poison, <4 x i32> zeroinitializer
%23 = add nsw <4 x i32> %22, <i32 -65504, i32 -65280, i32 -65072, i32 -63744>
%24 = icmp ult <4 x i32> %23, <i32 7, i32 96, i32 64, i32 512>
%25 = and i32 %0, -65536
%26 = icmp eq i32 %25, 131072
%27 = bitcast <4 x i1> %24 to i4
%28 = icmp ne i4 %27, 0
%29 = or i1 %28, %26
%30 = or i1 %29, %20
br i1 %30, label %32, label %31
31: ; preds = %18, %3
br label %32
32: ; preds = %5, %10, %15, %18, %1, %31
%33 = phi i32 [ 1, %31 ], [ 0, %1 ], [ 2, %18 ], [ 2, %15 ], [ 2, %10 ], [ 2, %5 ]
ret i32 %33
}