int validate_utf8_char(unsigned char *untrusted_c) {
  int tails_count = 0;
  int total_size = 0;
  if (*untrusted_c <= 0x7F) {
    return 1;
  } else if (*untrusted_c >= 0xC2 && *untrusted_c <= 0xDF) {
    total_size = 2;
    tails_count = 1;
  } else
    switch (*untrusted_c) {
    case 0xE0:
      untrusted_c++;
      total_size = 3;
      if (*untrusted_c >= 0xA0 && *untrusted_c <= 0xBF)
        tails_count = 1;
      else
        return 0;
      break;
    case 0xE1:
    case 0xE2:
    case 0xE3:
    case 0xE4:
    case 0xE5:
    case 0xE6:
    case 0xE7:
    case 0xE8:
    case 0xE9:
    case 0xEA:
    case 0xEB:
    case 0xEC:
    case 0xEE:
    case 0xEF:
      total_size = 3;
      tails_count = 2;
      break;
    case 0xED:
      untrusted_c++;
      total_size = 3;
      if (*untrusted_c >= 0x80 && *untrusted_c <= 0x9F)
        tails_count = 1;
      else
        return 0;
      break;
    case 0xF0:
      untrusted_c++;
      total_size = 4;
      if (*untrusted_c >= 0x90 && *untrusted_c <= 0xBF)
        tails_count = 2;
      else
        return 0;
      break;
    case 0xF1:
    case 0xF2:
    case 0xF3:
      total_size = 4;
      tails_count = 3;
      break;
    case 0xF4:
      untrusted_c++;
      if (*untrusted_c >= 0x80 && *untrusted_c <= 0x8F)
        tails_count = 2;
      else
        return 0;
      break;
    default:
      return 0;
    }
  while (tails_count-- > 0) {
    untrusted_c++;
    if (!(*untrusted_c >= 0x80 && *untrusted_c <= 0xBF))
      return 0;
  }
  return total_size;
}


x86 assembly (clang, -O0):
<validate_utf8_char>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x7f,%eax
jg     1132 <validate_utf8_char+0x32>
movl   $0x1,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0xc2,%eax
jl     1169 <validate_utf8_char+0x69>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0xdf,%eax
jg     1169 <validate_utf8_char+0x69>
movl   $0x2,-0x18(%rbp)
movl   $0x1,-0x14(%rbp)
jmp    1318 <validate_utf8_char+0x218>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
add    $0xffffff20,%eax
mov    %eax,%ecx
mov    %rcx,-0x20(%rbp)
sub    $0x14,%eax
ja     1307 <validate_utf8_char+0x207>
mov    -0x20(%rbp),%rax
lea    0xe71(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
movl   $0x3,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0xa0,%eax
jl     11db <validate_utf8_char+0xdb>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0xbf,%eax
jg     11db <validate_utf8_char+0xdb>
movl   $0x1,-0x14(%rbp)
jmp    11e7 <validate_utf8_char+0xe7>
movl   $0x0,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
jmp    1313 <validate_utf8_char+0x213>
movl   $0x3,-0x18(%rbp)
movl   $0x2,-0x14(%rbp)
jmp    1313 <validate_utf8_char+0x213>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
movl   $0x3,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x80,%eax
jl     1242 <validate_utf8_char+0x142>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x9f,%eax
jg     1242 <validate_utf8_char+0x142>
movl   $0x1,-0x14(%rbp)
jmp    124e <validate_utf8_char+0x14e>
movl   $0x0,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
jmp    1313 <validate_utf8_char+0x213>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
movl   $0x4,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x90,%eax
jl     1296 <validate_utf8_char+0x196>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0xbf,%eax
jg     1296 <validate_utf8_char+0x196>
movl   $0x2,-0x14(%rbp)
jmp    12a2 <validate_utf8_char+0x1a2>
movl   $0x0,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
jmp    1313 <validate_utf8_char+0x213>
movl   $0x4,-0x18(%rbp)
movl   $0x3,-0x14(%rbp)
jmp    1313 <validate_utf8_char+0x213>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x80,%eax
jl     12f6 <validate_utf8_char+0x1f6>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x8f,%eax
jg     12f6 <validate_utf8_char+0x1f6>
movl   $0x2,-0x14(%rbp)
jmp    1302 <validate_utf8_char+0x202>
movl   $0x0,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
jmp    1313 <validate_utf8_char+0x213>
movl   $0x0,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
jmp    1318 <validate_utf8_char+0x218>
jmp    131d <validate_utf8_char+0x21d>
jmp    1322 <validate_utf8_char+0x222>
mov    -0x14(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x14(%rbp)
cmp    $0x0,%eax
jle    1377 <validate_utf8_char+0x277>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x80,%eax
jl     1366 <validate_utf8_char+0x266>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0xbf,%eax
jle    1372 <validate_utf8_char+0x272>
movl   $0x0,-0x4(%rbp)
jmp    137d <validate_utf8_char+0x27d>
jmp    1322 <validate_utf8_char+0x222>
mov    -0x18(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<validate_utf8_char>:
mov    (%rdi),%sil
mov    $0x1,%eax
test   %sil,%sil
js     110e <validate_utf8_char+0xe>
ret
lea    0x3e(%rsi),%ecx
xor    %eax,%eax
cmp    $0x1e,%cl
jae    1124 <validate_utf8_char+0x24>
mov    $0x2,%ecx
xor    %r8d,%r8d
xor    %esi,%esi
jmp    114c <validate_utf8_char+0x4c>
add    $0x20,%sil
cmp    $0x14,%sil
ja     110d <validate_utf8_char+0xd>
mov    $0x3,%ecx
mov    $0x1,%r8b
movzbl %sil,%eax
lea    0xebf(%rip),%rsi
movslq (%rsi,%rax,4),%rax
add    %rsi,%rax
xor    %esi,%esi
jmp    *%rax
mov    0x1(%rdi),%dl
xor    %eax,%eax
cmp    $0xc0,%dl
cmovl  %ecx,%eax
jge    110d <validate_utf8_char+0xd>
test   %r8b,%r8b
je     110d <validate_utf8_char+0xd>
mov    0x2(%rdi),%dl
xor    %eax,%eax
cmp    $0xc0,%dl
cmovl  %ecx,%eax
jge    110d <validate_utf8_char+0xd>
xor    $0x1,%sil
jne    110d <validate_utf8_char+0xd>
xor    %eax,%eax
cmpb   $0xc0,0x3(%rdi)
cmovl  %ecx,%eax
ret
mov    $0x4,%ecx
mov    $0x1,%r8b
mov    $0x1,%sil
jmp    114c <validate_utf8_char+0x4c>
mov    0x1(%rdi),%dl
and    $0xe0,%dl
xor    %eax,%eax
cmp    $0xa0,%dl
je     11a6 <validate_utf8_char+0xa6>
jmp    110d <validate_utf8_char+0xd>
xor    %eax,%eax
cmpb   $0xa0,0x1(%rdi)
jge    110d <validate_utf8_char+0xd>
add    $0x1,%rdi
jmp    111d <validate_utf8_char+0x1d>
xor    %ecx,%ecx
cmpb   $0x8f,0x1(%rdi)
jg     11df <validate_utf8_char+0xdf>
add    $0x1,%rdi
jmp    1120 <validate_utf8_char+0x20>
mov    0x1(%rdi),%cl
add    $0x70,%cl
xor    %eax,%eax
cmp    $0x30,%cl
jae    110d <validate_utf8_char+0xd>
add    $0x1,%rdi
mov    $0x4,%ecx
jmp    1120 <validate_utf8_char+0x20>
xor    %eax,%eax
ret

LLVM IR (-O0):
define i32 @validate_utf8_char(i8* %0) {
%2 = alloca i32
%3 = alloca i8*
%4 = alloca i32
%5 = alloca i32
store i8* %0, i8** %3
store i32 0, i32* %4
store i32 0, i32* %5
%6 = load i8*, i8** %3
%7 = load i8, i8* %6
%8 = zext i8 %7 to i32
%9 = icmp sle i32 %8, 127
br i1 %9, label %10, label %11
10: ; preds = %1
store i32 1, i32* %2
br label %112
11: ; preds = %1
%12 = load i8*, i8** %3
%13 = load i8, i8* %12
%14 = zext i8 %13 to i32
%15 = icmp sge i32 %14, 194
br i1 %15, label %16, label %22
16: ; preds = %11
%17 = load i8*, i8** %3
%18 = load i8, i8* %17
%19 = zext i8 %18 to i32
%20 = icmp sle i32 %19, 223
br i1 %20, label %21, label %22
21: ; preds = %16
store i32 2, i32* %5
store i32 1, i32* %4
br label %90
22: ; preds = %16, %11
%23 = load i8*, i8** %3
%24 = load i8, i8* %23
%25 = zext i8 %24 to i32
switch i32 %25, label %88 [
i32 224, label %26
i32 225, label %41
i32 226, label %41
i32 227, label %41
i32 228, label %41
i32 229, label %41
i32 230, label %41
i32 231, label %41
i32 232, label %41
i32 233, label %41
i32 234, label %41
i32 235, label %41
i32 236, label %41
i32 238, label %41
i32 239, label %41
i32 237, label %42
i32 240, label %57
i32 241, label %72
i32 242, label %72
i32 243, label %72
i32 244, label %73
]
26: ; preds = %22
%27 = load i8*, i8** %3
%28 = getelementptr inbounds i8, i8* %27, i32 1
store i8* %28, i8** %3
store i32 3, i32* %5
%29 = load i8*, i8** %3
%30 = load i8, i8* %29
%31 = zext i8 %30 to i32
%32 = icmp sge i32 %31, 160
br i1 %32, label %33, label %39
33: ; preds = %26
%34 = load i8*, i8** %3
%35 = load i8, i8* %34
%36 = zext i8 %35 to i32
%37 = icmp sle i32 %36, 191
br i1 %37, label %38, label %39
38: ; preds = %33
store i32 1, i32* %4
br label %40
39: ; preds = %33, %26
store i32 0, i32* %2
br label %112
40: ; preds = %38
br label %89
41: ; preds = %22, %22, %22, %22, %22, %22, %22, %22, %22, %22, %22, %22, %22, %22
store i32 3, i32* %5
store i32 2, i32* %4
br label %89
42: ; preds = %22
%43 = load i8*, i8** %3
%44 = getelementptr inbounds i8, i8* %43, i32 1
store i8* %44, i8** %3
store i32 3, i32* %5
%45 = load i8*, i8** %3
%46 = load i8, i8* %45
%47 = zext i8 %46 to i32
%48 = icmp sge i32 %47, 128
br i1 %48, label %49, label %55
49: ; preds = %42
%50 = load i8*, i8** %3
%51 = load i8, i8* %50
%52 = zext i8 %51 to i32
%53 = icmp sle i32 %52, 159
br i1 %53, label %54, label %55
54: ; preds = %49
store i32 1, i32* %4
br label %56
55: ; preds = %49, %42
store i32 0, i32* %2
br label %112
56: ; preds = %54
br label %89
57: ; preds = %22
%58 = load i8*, i8** %3
%59 = getelementptr inbounds i8, i8* %58, i32 1
store i8* %59, i8** %3
store i32 4, i32* %5
%60 = load i8*, i8** %3
%61 = load i8, i8* %60
%62 = zext i8 %61 to i32
%63 = icmp sge i32 %62, 144
br i1 %63, label %64, label %70
64: ; preds = %57
%65 = load i8*, i8** %3
%66 = load i8, i8* %65
%67 = zext i8 %66 to i32
%68 = icmp sle i32 %67, 191
br i1 %68, label %69, label %70
69: ; preds = %64
store i32 2, i32* %4
br label %71
70: ; preds = %64, %57
store i32 0, i32* %2
br label %112
71: ; preds = %69
br label %89
72: ; preds = %22, %22, %22
store i32 4, i32* %5
store i32 3, i32* %4
br label %89
73: ; preds = %22
%74 = load i8*, i8** %3
%75 = getelementptr inbounds i8, i8* %74, i32 1
store i8* %75, i8** %3
%76 = load i8*, i8** %3
%77 = load i8, i8* %76
%78 = zext i8 %77 to i32
%79 = icmp sge i32 %78, 128
br i1 %79, label %80, label %86
80: ; preds = %73
%81 = load i8*, i8** %3
%82 = load i8, i8* %81
%83 = zext i8 %82 to i32
%84 = icmp sle i32 %83, 143
br i1 %84, label %85, label %86
85: ; preds = %80
store i32 2, i32* %4
br label %87
86: ; preds = %80, %73
store i32 0, i32* %2
br label %112
87: ; preds = %85
br label %89
88: ; preds = %22
store i32 0, i32* %2
br label %112
89: ; preds = %87, %72, %71, %56, %41, %40
br label %90
90: ; preds = %89, %21
br label %91
91: ; preds = %90
br label %92
92: ; preds = %109, %91
%93 = load i32, i32* %4
%94 = add nsw i32 %93, -1
store i32 %94, i32* %4
%95 = icmp sgt i32 %93, 0
br i1 %95, label %96, label %110
96: ; preds = %92
%97 = load i8*, i8** %3
%98 = getelementptr inbounds i8, i8* %97, i32 1
store i8* %98, i8** %3
%99 = load i8*, i8** %3
%100 = load i8, i8* %99
%101 = zext i8 %100 to i32
%102 = icmp sge i32 %101, 128
br i1 %102, label %103, label %108
103: ; preds = %96
%104 = load i8*, i8** %3
%105 = load i8, i8* %104
%106 = zext i8 %105 to i32
%107 = icmp sle i32 %106, 191
br i1 %107, label %109, label %108
108: ; preds = %103, %96
store i32 0, i32* %2
br label %112
109: ; preds = %103
br label %92
110: ; preds = %92
%111 = load i32, i32* %5
store i32 %111, i32* %2
br label %112
112: ; preds = %110, %108, %88, %86, %70, %55, %39, %10
%113 = load i32, i32* %2
ret i32 %113
}

LLVM IR (-O2):
define i32 @validate_utf8_char(i8* %0) {
%2 = load i8, i8* %0
%3 = icmp sgt i8 %2, -1
br i1 %3, label %52, label %4
4: ; preds = %1
%5 = add nsw i8 %2, 62
%6 = icmp ult i8 %5, 30
br i1 %6, label %27, label %7
7: ; preds = %4
switch i8 %2, label %52 [
i8 -32, label %8
i8 -31, label %27
i8 -30, label %27
i8 -29, label %27
i8 -28, label %27
i8 -27, label %27
i8 -26, label %27
i8 -25, label %27
i8 -24, label %27
i8 -23, label %27
i8 -22, label %27
i8 -21, label %27
i8 -20, label %27
i8 -18, label %27
i8 -17, label %27
i8 -19, label %13
i8 -16, label %17
i8 -15, label %22
i8 -14, label %22
i8 -13, label %22
i8 -12, label %23
]
8: ; preds = %7
%9 = getelementptr inbounds i8, i8* %0, i64 1
%10 = load i8, i8* %9
%11 = and i8 %10, -32
%12 = icmp eq i8 %11, -96
br i1 %12, label %27, label %52
13: ; preds = %7
%14 = getelementptr inbounds i8, i8* %0, i64 1
%15 = load i8, i8* %14
%16 = icmp slt i8 %15, -96
br i1 %16, label %27, label %52
17: ; preds = %7
%18 = getelementptr inbounds i8, i8* %0, i64 1
%19 = load i8, i8* %18
%20 = add i8 %19, 112
%21 = icmp ult i8 %20, 48
br i1 %21, label %27, label %52
22: ; preds = %7, %7, %7
br label %27
23: ; preds = %7
%24 = getelementptr inbounds i8, i8* %0, i64 1
%25 = load i8, i8* %24
%26 = icmp slt i8 %25, -112
br i1 %26, label %27, label %52
27: ; preds = %23, %17, %13, %7, %7, %7, %7, %7, %7, %7, %7, %7, %7, %7, %7, %7, %7, %8, %4, %22
%28 = phi i8* [ %0, %22 ], [ %0, %4 ], [ %9, %8 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %0, %7 ], [ %14, %13 ], [ %18, %17 ], [ %24, %23 ]
%29 = phi i1 [ true, %22 ], [ false, %4 ], [ false, %8 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ true, %7 ], [ false, %13 ], [ true, %17 ], [ true, %23 ]
%30 = phi i1 [ true, %22 ], [ false, %4 ], [ false, %8 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %7 ], [ false, %13 ], [ false, %17 ], [ false, %23 ]
%31 = phi i32 [ 4, %22 ], [ 2, %4 ], [ 3, %8 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %7 ], [ 3, %13 ], [ 4, %17 ], [ 0, %23 ]
%32 = getelementptr inbounds i8, i8* %28, i64 1
%33 = load i8, i8* %32
%34 = icmp slt i8 %33, -64
%35 = xor i1 %34, true
%36 = xor i1 %29, true
%37 = or i1 %35, %36
%38 = select i1 %35, i32 0, i32 %31
br i1 %37, label %52, label %39
39: ; preds = %27
%40 = getelementptr inbounds i8, i8* %28, i64 2
%41 = load i8, i8* %40
%42 = icmp slt i8 %41, -64
%43 = xor i1 %42, true
%44 = xor i1 %30, true
%45 = or i1 %43, %44
%46 = select i1 %43, i32 0, i32 %31
br i1 %45, label %52, label %47
47: ; preds = %39
%48 = getelementptr inbounds i8, i8* %28, i64 3
%49 = load i8, i8* %48
%50 = icmp slt i8 %49, -64
%51 = select i1 %50, i32 %31, i32 0
br label %52
52: ; preds = %47, %27, %39, %7, %23, %17, %13, %8, %1
%53 = phi i32 [ 1, %1 ], [ 0, %8 ], [ 0, %13 ], [ 0, %17 ], [ 0, %23 ], [ 0, %7 ], [ %38, %27 ], [ %46, %39 ], [ %51, %47 ]
ret i32 %53
}