int unicode_width(unsigned long c, int tab_size) {
  if (c >= 0x1100 &&
      (c <= 0x115f || c == 0x2329 || c == 0x232a ||
       (c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) ||
       (c >= 0xac00 && c <= 0xd7a3) || (c >= 0xf900 && c <= 0xfaff) ||
       (c >= 0xfe30 && c <= 0xfe6f) || (c >= 0xff00 && c <= 0xff60) ||
       (c >= 0xffe0 && c <= 0xffe6) || (c >= 0x20000 && c <= 0x2fffd) ||
       (c >= 0x30000 && c <= 0x3fffd)))
    return 2;
  if ((c >= 0x0300 && c <= 0x036f) || (c >= 0x1dc0 && c <= 0x1dff) ||
      (c >= 0x20d0 && c <= 0x20ff) || (c >= 0xfe20 && c <= 0xfe2f))
    return 0;
  if (c == '\t')
    return tab_size;
  return 1;
}


x86 assembly (clang, -O0):
<unicode_width>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
cmpq   $0x1100,-0x10(%rbp)
jb     123d <unicode_width+0x13d>
cmpq   $0x115f,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0x2329,-0x10(%rbp)
je     1231 <unicode_width+0x131>
cmpq   $0x232a,-0x10(%rbp)
je     1231 <unicode_width+0x131>
cmpq   $0x2e80,-0x10(%rbp)
jb     116d <unicode_width+0x6d>
cmpq   $0xa4cf,-0x10(%rbp)
ja     116d <unicode_width+0x6d>
cmpq   $0x303f,-0x10(%rbp)
jne    1231 <unicode_width+0x131>
cmpq   $0xac00,-0x10(%rbp)
jb     1189 <unicode_width+0x89>
cmpq   $0xd7a3,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0xf900,-0x10(%rbp)
jb     11a5 <unicode_width+0xa5>
cmpq   $0xfaff,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0xfe30,-0x10(%rbp)
jb     11c1 <unicode_width+0xc1>
cmpq   $0xfe6f,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0xff00,-0x10(%rbp)
jb     11dd <unicode_width+0xdd>
cmpq   $0xff60,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0xffe0,-0x10(%rbp)
jb     11f9 <unicode_width+0xf9>
cmpq   $0xffe6,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0x20000,-0x10(%rbp)
jb     1215 <unicode_width+0x115>
cmpq   $0x2fffd,-0x10(%rbp)
jbe    1231 <unicode_width+0x131>
cmpq   $0x30000,-0x10(%rbp)
jb     123d <unicode_width+0x13d>
cmpq   $0x3fffd,-0x10(%rbp)
ja     123d <unicode_width+0x13d>
movl   $0x2,-0x4(%rbp)
jmp    12d6 <unicode_width+0x1d6>
cmpq   $0x300,-0x10(%rbp)
jb     1259 <unicode_width+0x159>
cmpq   $0x36f,-0x10(%rbp)
jbe    12ad <unicode_width+0x1ad>
cmpq   $0x1dc0,-0x10(%rbp)
jb     1275 <unicode_width+0x175>
cmpq   $0x1dff,-0x10(%rbp)
jbe    12ad <unicode_width+0x1ad>
cmpq   $0x20d0,-0x10(%rbp)
jb     1291 <unicode_width+0x191>
cmpq   $0x20ff,-0x10(%rbp)
jbe    12ad <unicode_width+0x1ad>
cmpq   $0xfe20,-0x10(%rbp)
jb     12b9 <unicode_width+0x1b9>
cmpq   $0xfe2f,-0x10(%rbp)
ja     12b9 <unicode_width+0x1b9>
movl   $0x0,-0x4(%rbp)
jmp    12d6 <unicode_width+0x1d6>
cmpq   $0x9,-0x10(%rbp)
jne    12cf <unicode_width+0x1cf>
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    12d6 <unicode_width+0x1d6>
movl   $0x1,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<unicode_width>:
cmp    $0x1100,%rdi
jb     11c4 <unicode_width+0xc4>
mov    $0x2,%eax
cmp    $0x1160,%rdi
jb     120c <unicode_width+0x10c>
lea    -0x2329(%rdi),%rcx
cmp    $0x2,%rcx
jb     120c <unicode_width+0x10c>
lea    -0x2e80(%rdi),%rcx
cmp    $0x7650,%rcx
setb   %r8b
cmp    $0x303f,%rdi
setne  %dl
lea    -0x30000(%rdi),%rcx
cmp    $0xfffe,%rcx
jb     120c <unicode_width+0x10c>
lea    -0x20000(%rdi),%rcx
cmp    $0xfffe,%rcx
jb     120c <unicode_width+0x10c>
lea    -0xffe0(%rdi),%rcx
cmp    $0x7,%rcx
jb     120c <unicode_width+0x10c>
lea    -0xff00(%rdi),%rcx
cmp    $0x61,%rcx
jb     120c <unicode_width+0x10c>
lea    -0xfe30(%rdi),%rcx
cmp    $0x40,%rcx
jb     120c <unicode_width+0x10c>
lea    -0xf900(%rdi),%rcx
cmp    $0x200,%rcx
jb     120c <unicode_width+0x10c>
lea    -0xac00(%rdi),%rcx
cmp    $0x2ba4,%rcx
jb     120c <unicode_width+0x10c>
and    %r8b,%dl
jne    120c <unicode_width+0x10c>
mov    %rdi,%rcx
and    $0xfffffffffffffff0,%rcx
xor    %eax,%eax
cmp    $0xfe20,%rcx
je     120c <unicode_width+0x10c>
lea    -0x20d0(%rdi),%rcx
cmp    $0x30,%rcx
jb     120c <unicode_width+0x10c>
lea    -0x300(%rdi),%rcx
cmp    $0x70,%rcx
jb     120c <unicode_width+0x10c>
mov    %rdi,%rcx
and    $0xffffffffffffffc0,%rcx
cmp    $0x1dc0,%rcx
je     120c <unicode_width+0x10c>
cmp    $0x9,%rdi
mov    $0x1,%eax
cmove  %esi,%eax
ret

LLVM IR (-O0):
define i32 @unicode_width(i64 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i64
%5 = alloca i32
store i64 %0, i64* %4
store i32 %1, i32* %5
%6 = load i64, i64* %4
%7 = icmp uge i64 %6, 4352
br i1 %7, label %8, label %69
8: ; preds = %2
%9 = load i64, i64* %4
%10 = icmp ule i64 %9, 4447
br i1 %10, label %68, label %11
11: ; preds = %8
%12 = load i64, i64* %4
%13 = icmp eq i64 %12, 9001
br i1 %13, label %68, label %14
14: ; preds = %11
%15 = load i64, i64* %4
%16 = icmp eq i64 %15, 9002
br i1 %16, label %68, label %17
17: ; preds = %14
%18 = load i64, i64* %4
%19 = icmp uge i64 %18, 11904
br i1 %19, label %20, label %26
20: ; preds = %17
%21 = load i64, i64* %4
%22 = icmp ule i64 %21, 42191
br i1 %22, label %23, label %26
23: ; preds = %20
%24 = load i64, i64* %4
%25 = icmp ne i64 %24, 12351
br i1 %25, label %68, label %26
26: ; preds = %23, %20, %17
%27 = load i64, i64* %4
%28 = icmp uge i64 %27, 44032
br i1 %28, label %29, label %32
29: ; preds = %26
%30 = load i64, i64* %4
%31 = icmp ule i64 %30, 55203
br i1 %31, label %68, label %32
32: ; preds = %29, %26
%33 = load i64, i64* %4
%34 = icmp uge i64 %33, 63744
br i1 %34, label %35, label %38
35: ; preds = %32
%36 = load i64, i64* %4
%37 = icmp ule i64 %36, 64255
br i1 %37, label %68, label %38
38: ; preds = %35, %32
%39 = load i64, i64* %4
%40 = icmp uge i64 %39, 65072
br i1 %40, label %41, label %44
41: ; preds = %38
%42 = load i64, i64* %4
%43 = icmp ule i64 %42, 65135
br i1 %43, label %68, label %44
44: ; preds = %41, %38
%45 = load i64, i64* %4
%46 = icmp uge i64 %45, 65280
br i1 %46, label %47, label %50
47: ; preds = %44
%48 = load i64, i64* %4
%49 = icmp ule i64 %48, 65376
br i1 %49, label %68, label %50
50: ; preds = %47, %44
%51 = load i64, i64* %4
%52 = icmp uge i64 %51, 65504
br i1 %52, label %53, label %56
53: ; preds = %50
%54 = load i64, i64* %4
%55 = icmp ule i64 %54, 65510
br i1 %55, label %68, label %56
56: ; preds = %53, %50
%57 = load i64, i64* %4
%58 = icmp uge i64 %57, 131072
br i1 %58, label %59, label %62
59: ; preds = %56
%60 = load i64, i64* %4
%61 = icmp ule i64 %60, 196605
br i1 %61, label %68, label %62
62: ; preds = %59, %56
%63 = load i64, i64* %4
%64 = icmp uge i64 %63, 196608
br i1 %64, label %65, label %69
65: ; preds = %62
%66 = load i64, i64* %4
%67 = icmp ule i64 %66, 262141
br i1 %67, label %68, label %69
68: ; preds = %65, %59, %53, %47, %41, %35, %29, %23, %14, %11, %8
store i32 2, i32* %3
br label %100
69: ; preds = %65, %62, %2
%70 = load i64, i64* %4
%71 = icmp uge i64 %70, 768
br i1 %71, label %72, label %75
72: ; preds = %69
%73 = load i64, i64* %4
%74 = icmp ule i64 %73, 879
br i1 %74, label %93, label %75
75: ; preds = %72, %69
%76 = load i64, i64* %4
%77 = icmp uge i64 %76, 7616
br i1 %77, label %78, label %81
78: ; preds = %75
%79 = load i64, i64* %4
%80 = icmp ule i64 %79, 7679
br i1 %80, label %93, label %81
81: ; preds = %78, %75
%82 = load i64, i64* %4
%83 = icmp uge i64 %82, 8400
br i1 %83, label %84, label %87
84: ; preds = %81
%85 = load i64, i64* %4
%86 = icmp ule i64 %85, 8447
br i1 %86, label %93, label %87
87: ; preds = %84, %81
%88 = load i64, i64* %4
%89 = icmp uge i64 %88, 65056
br i1 %89, label %90, label %94
90: ; preds = %87
%91 = load i64, i64* %4
%92 = icmp ule i64 %91, 65071
br i1 %92, label %93, label %94
93: ; preds = %90, %84, %78, %72
store i32 0, i32* %3
br label %100
94: ; preds = %90, %87
%95 = load i64, i64* %4
%96 = icmp eq i64 %95, 9
br i1 %96, label %97, label %99
97: ; preds = %94
%98 = load i32, i32* %5
store i32 %98, i32* %3
br label %100
99: ; preds = %94
store i32 1, i32* %3
br label %100
100: ; preds = %99, %97, %93, %68
%101 = load i32, i32* %3
ret i32 %101
}

LLVM IR (-O2):
define i32 @unicode_width(i64 %0, i32 %1) {
%3 = icmp ugt i64 %0, 4351
br i1 %3, label %4, label %35
4: ; preds = %2
%5 = icmp ult i64 %0, 4448
%6 = add i64 %0, -9001
%7 = icmp ult i64 %6, 2
%8 = or i1 %5, %7
br i1 %8, label %50, label %9
9: ; preds = %4
%10 = add i64 %0, -11904
%11 = icmp ult i64 %10, 30288
%12 = icmp ne i64 %0, 12351
%13 = and i1 %12, %11
%14 = add i64 %0, -44032
%15 = icmp ult i64 %14, 11172
%16 = or i1 %15, %13
%17 = add i64 %0, -63744
%18 = icmp ult i64 %17, 512
%19 = or i1 %18, %16
%20 = add i64 %0, -65072
%21 = icmp ult i64 %20, 64
%22 = or i1 %21, %19
%23 = add i64 %0, -65280
%24 = icmp ult i64 %23, 97
%25 = or i1 %24, %22
%26 = add i64 %0, -65504
%27 = icmp ult i64 %26, 7
%28 = or i1 %27, %25
%29 = add i64 %0, -131072
%30 = icmp ult i64 %29, 65534
%31 = or i1 %30, %28
%32 = add i64 %0, -196608
%33 = icmp ult i64 %32, 65534
%34 = or i1 %33, %31
br i1 %34, label %50, label %35
35: ; preds = %9, %2
%36 = add i64 %0, -768
%37 = icmp ult i64 %36, 112
%38 = and i64 %0, -64
%39 = icmp eq i64 %38, 7616
%40 = or i1 %37, %39
%41 = add i64 %0, -8400
%42 = icmp ult i64 %41, 48
%43 = or i1 %42, %40
%44 = and i64 %0, -16
%45 = icmp eq i64 %44, 65056
%46 = or i1 %45, %43
br i1 %46, label %50, label %47
47: ; preds = %35
%48 = icmp eq i64 %0, 9
%49 = select i1 %48, i32 %1, i32 1
br label %50
50: ; preds = %47, %35, %4, %9
%51 = phi i32 [ 2, %9 ], [ 2, %4 ], [ 0, %35 ], [ %49, %47 ]
ret i32 %51
}