int valid_utf8_char(const char *str) {
  unsigned char c = (unsigned char)*str;
  int n = 0;
  if ((c & 0x80) == 0x00) {
    n = 0;
  } else if ((c & 0xe0) == 0xc0) {
    n = 1;
  } else if ((c & 0xf0) == 0xe0) {
    n = 2;
  } else if ((c & 0xf8) == 0xf0) {
    n = 3;
  } else if ((c & 0xfc) == 0xf8) {
    n = 4;
  } else if ((c & 0xfe) == 0xfc) {
    n = 5;
  } else {
    return -1;
  }
  int i;
  for (i = 0; i < n; i++) {
    if ((((unsigned char)(str[i + 1])) & 0xc0) != 0x80) {
      return -1;
    }
  }
  return n + 1;
}


x86 assembly (clang, -O0):
<valid_utf8_char>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    -0x10(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x11(%rbp)
movl   $0x0,-0x18(%rbp)
movzbl -0x11(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
jne    1136 <valid_utf8_char+0x36>
movl   $0x0,-0x18(%rbp)
jmp    11fb <valid_utf8_char+0xfb>
movzbl -0x11(%rbp),%eax
and    $0xe0,%eax
cmp    $0xc0,%eax
jne    1156 <valid_utf8_char+0x56>
movl   $0x1,-0x18(%rbp)
jmp    11f6 <valid_utf8_char+0xf6>
movzbl -0x11(%rbp),%eax
and    $0xf0,%eax
cmp    $0xe0,%eax
jne    1176 <valid_utf8_char+0x76>
movl   $0x2,-0x18(%rbp)
jmp    11f1 <valid_utf8_char+0xf1>
movzbl -0x11(%rbp),%eax
and    $0xf8,%eax
cmp    $0xf0,%eax
jne    1196 <valid_utf8_char+0x96>
movl   $0x3,-0x18(%rbp)
jmp    11ec <valid_utf8_char+0xec>
movzbl -0x11(%rbp),%eax
and    $0xfc,%eax
cmp    $0xf8,%eax
jne    11b6 <valid_utf8_char+0xb6>
movl   $0x4,-0x18(%rbp)
jmp    11e7 <valid_utf8_char+0xe7>
movzbl -0x11(%rbp),%eax
and    $0xfe,%eax
cmp    $0xfc,%eax
jne    11d6 <valid_utf8_char+0xd6>
movl   $0x5,-0x18(%rbp)
jmp    11e2 <valid_utf8_char+0xe2>
movl   $0xffffffff,-0x4(%rbp)
jmp    1257 <valid_utf8_char+0x157>
jmp    11e7 <valid_utf8_char+0xe7>
jmp    11ec <valid_utf8_char+0xec>
jmp    11f1 <valid_utf8_char+0xf1>
jmp    11f6 <valid_utf8_char+0xf6>
jmp    11fb <valid_utf8_char+0xfb>
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x18(%rbp),%eax
jge    124e <valid_utf8_char+0x14e>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movzbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
je     123b <valid_utf8_char+0x13b>
movl   $0xffffffff,-0x4(%rbp)
jmp    1257 <valid_utf8_char+0x157>
jmp    1240 <valid_utf8_char+0x140>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1202 <valid_utf8_char+0x102>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<valid_utf8_char>:
movzbl (%rdi),%ecx
test   $0x80,%cl
jne    1113 <valid_utf8_char+0x13>
mov    $0x1,%eax
mov    $0x1,%cl
xor    %esi,%esi
jmp    1129 <valid_utf8_char+0x29>
mov    %ecx,%eax
and    $0xffffffe0,%eax
cmp    $0xc0,%eax
jne    118e <valid_utf8_char+0x8e>
mov    $0x2,%eax
mov    $0x1,%sil
xor    %ecx,%ecx
xor    %edx,%edx
xor    %r10d,%r10d
xor    %r9d,%r9d
xor    %r8d,%r8d
test   %cl,%cl
jne    118d <valid_utf8_char+0x8d>
mov    0x1(%rdi),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1188 <valid_utf8_char+0x88>
test   %sil,%sil
jne    118d <valid_utf8_char+0x8d>
mov    0x2(%rdi),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1188 <valid_utf8_char+0x88>
test   %dl,%dl
jne    118d <valid_utf8_char+0x8d>
mov    0x3(%rdi),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1188 <valid_utf8_char+0x88>
test   %r10b,%r10b
jne    118d <valid_utf8_char+0x8d>
mov    0x4(%rdi),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1188 <valid_utf8_char+0x88>
test   %r9b,%r9b
jne    118d <valid_utf8_char+0x8d>
mov    0x5(%rdi),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1188 <valid_utf8_char+0x88>
xor    $0x1,%r8b
je     118d <valid_utf8_char+0x8d>
mov    $0xffffffff,%eax
ret
mov    %ecx,%eax
and    $0xfffffff0,%eax
cmp    $0xe0,%eax
jne    11a7 <valid_utf8_char+0xa7>
mov    $0x3,%eax
mov    $0x1,%dl
xor    %ecx,%ecx
xor    %esi,%esi
jmp    112b <valid_utf8_char+0x2b>
mov    %ecx,%eax
and    $0xfffffff8,%eax
cmp    $0xf0,%eax
jne    11c6 <valid_utf8_char+0xc6>
mov    $0x4,%eax
mov    $0x1,%r10b
xor    %ecx,%ecx
xor    %esi,%esi
xor    %edx,%edx
jmp    112e <valid_utf8_char+0x2e>
mov    %ecx,%eax
and    $0xfffffffc,%eax
cmp    $0xf8,%eax
jne    11e8 <valid_utf8_char+0xe8>
mov    $0x5,%eax
mov    $0x1,%r9b
xor    %ecx,%ecx
xor    %esi,%esi
xor    %edx,%edx
xor    %r10d,%r10d
jmp    1131 <valid_utf8_char+0x31>
and    $0xfffffffe,%ecx
mov    $0xffffffff,%eax
cmp    $0xfc,%ecx
jne    118d <valid_utf8_char+0x8d>
mov    $0x6,%eax
mov    $0x1,%r8b
xor    %ecx,%ecx
xor    %esi,%esi
xor    %edx,%edx
xor    %r10d,%r10d
xor    %r9d,%r9d
test   %cl,%cl
jne    118d <valid_utf8_char+0x8d>
jmp    1138 <valid_utf8_char+0x38>

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

LLVM IR (-O2):
define i32 @valid_utf8_char(i8* nocapture %0) {
%2 = load i8, i8* %0
%3 = zext i8 %2 to i32
%4 = and i32 %3, 128
%5 = icmp eq i32 %4, 0
br i1 %5, label %21, label %6
6: ; preds = %1
%7 = and i32 %3, 224
%8 = icmp eq i32 %7, 192
br i1 %8, label %21, label %9
9: ; preds = %6
%10 = and i32 %3, 240
%11 = icmp eq i32 %10, 224
br i1 %11, label %21, label %12
12: ; preds = %9
%13 = and i32 %3, 248
%14 = icmp eq i32 %13, 240
br i1 %14, label %21, label %15
15: ; preds = %12
%16 = and i32 %3, 252
%17 = icmp eq i32 %16, 248
br i1 %17, label %21, label %18
18: ; preds = %15
%19 = and i32 %3, 254
%20 = icmp eq i32 %19, 252
br i1 %20, label %21, label %62
21: ; preds = %1, %6, %9, %12, %15, %18
%22 = phi i1 [ false, %18 ], [ false, %15 ], [ false, %12 ], [ false, %9 ], [ false, %6 ], [ true, %1 ]
%23 = phi i1 [ false, %18 ], [ false, %15 ], [ false, %12 ], [ false, %9 ], [ true, %6 ], [ false, %1 ]
%24 = phi i1 [ false, %18 ], [ false, %15 ], [ false, %12 ], [ true, %9 ], [ false, %6 ], [ false, %1 ]
%25 = phi i1 [ false, %18 ], [ false, %15 ], [ true, %12 ], [ false, %9 ], [ false, %6 ], [ false, %1 ]
%26 = phi i1 [ false, %18 ], [ true, %15 ], [ false, %12 ], [ false, %9 ], [ false, %6 ], [ false, %1 ]
%27 = phi i1 [ true, %18 ], [ false, %15 ], [ false, %12 ], [ false, %9 ], [ false, %6 ], [ false, %1 ]
%28 = phi i32 [ 6, %18 ], [ 5, %15 ], [ 4, %12 ], [ 3, %9 ], [ 2, %6 ], [ 1, %1 ]
br i1 %22, label %62, label %29
29: ; preds = %21
%30 = getelementptr inbounds i8, i8* %0, i64 1
%31 = load i8, i8* %30
%32 = and i8 %31, -64
%33 = icmp eq i8 %32, -128
br i1 %33, label %34, label %61
34: ; preds = %29
br i1 %23, label %62, label %35
35: ; preds = %34
%36 = getelementptr inbounds i8, i8* %0, i64 2
%37 = load i8, i8* %36
%38 = and i8 %37, -64
%39 = icmp eq i8 %38, -128
br i1 %39, label %40, label %61
40: ; preds = %35
br i1 %24, label %62, label %41
41: ; preds = %40
%42 = getelementptr inbounds i8, i8* %0, i64 3
%43 = load i8, i8* %42
%44 = and i8 %43, -64
%45 = icmp eq i8 %44, -128
br i1 %45, label %46, label %61
46: ; preds = %41
br i1 %25, label %62, label %47
47: ; preds = %46
%48 = getelementptr inbounds i8, i8* %0, i64 4
%49 = load i8, i8* %48
%50 = and i8 %49, -64
%51 = icmp eq i8 %50, -128
br i1 %51, label %52, label %61
52: ; preds = %47
br i1 %26, label %62, label %53
53: ; preds = %52
%54 = getelementptr inbounds i8, i8* %0, i64 5
%55 = load i8, i8* %54
%56 = and i8 %55, -64
%57 = icmp eq i8 %56, -128
%58 = xor i1 %57, true
%59 = xor i1 %27, true
%60 = or i1 %58, %59
br i1 %60, label %61, label %62
61: ; preds = %53, %47, %41, %35, %29
br label %62
62: ; preds = %53, %21, %34, %40, %46, %52, %61, %18
%63 = phi i32 [ -1, %18 ], [ -1, %61 ], [ %28, %52 ], [ %28, %46 ], [ %28, %40 ], [ %28, %34 ], [ %28, %21 ], [ %28, %53 ]
ret i32 %63
}