int isUTF8(unsigned char *str, int length) {
  int i, mode = 0, m2;
  unsigned long ucs;
  unsigned char ch;
  for (i = 0; i < length; i++) {
    ch = str[i];
    if (mode == 0) {
      if ((ch & 0x80) == 0)
        continue;
      if ((ch & 0xe0) == 0xc0) {
        mode = m2 = 1;
        ucs = (ch & 0x1f);
        continue;
      }
      if ((ch & 0xf0) == 0xe0) {
        mode = m2 = 2;
        ucs = (ch & 0x0f);
        continue;
      }
      if ((ch & 0xf8) == 0xf0) {
        mode = m2 = 3;
        ucs = (ch & 0x07);
        continue;
      }
      if ((ch & 0xfc) == 0xf8) {
        mode = m2 = 4;
        ucs = (ch & 0x03);
        continue;
      }
      if ((ch & 0xfe) == 0xfc) {
        mode = m2 = 5;
        ucs = (ch & 0x01);
        continue;
      }
      return 0;
    } else {
      if ((ch & 0xc0) != 0x80)
        return 0;
      ucs <<= 6;
      ucs += (ch & 0x3f);
      mode--;
      if (!mode) {
        if (m2 == 1 && ucs < 0x0000080)
          return 0;
        if (m2 == 2 && ucs < 0x0000800)
          return 0;
        if (m2 == 3 && ucs < 0x0010000)
          return 0;
        if (m2 == 4 && ucs < 0x0200000)
          return 0;
        if (m2 == 5 && ucs < 0x4000000)
          return 0;
      }
    }
  }
  return 1;
}


x86 assembly (clang, -O0):
<isUTF8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
movl   $0x0,-0x1c(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1385 <isUTF8+0x285>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x29(%rbp)
cmpl   $0x0,-0x1c(%rbp)
jne    1264 <isUTF8+0x164>
movzbl -0x29(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
jne    1154 <isUTF8+0x54>
jmp    1377 <isUTF8+0x277>
movzbl -0x29(%rbp),%eax
and    $0xe0,%eax
cmp    $0xc0,%eax
jne    1188 <isUTF8+0x88>
movl   $0x1,-0x20(%rbp)
movl   $0x1,-0x1c(%rbp)
movzbl -0x29(%rbp),%eax
and    $0x1f,%eax
cltq
mov    %rax,-0x28(%rbp)
jmp    1377 <isUTF8+0x277>
movzbl -0x29(%rbp),%eax
and    $0xf0,%eax
cmp    $0xe0,%eax
jne    11bc <isUTF8+0xbc>
movl   $0x2,-0x20(%rbp)
movl   $0x2,-0x1c(%rbp)
movzbl -0x29(%rbp),%eax
and    $0xf,%eax
cltq
mov    %rax,-0x28(%rbp)
jmp    1377 <isUTF8+0x277>
movzbl -0x29(%rbp),%eax
and    $0xf8,%eax
cmp    $0xf0,%eax
jne    11f0 <isUTF8+0xf0>
movl   $0x3,-0x20(%rbp)
movl   $0x3,-0x1c(%rbp)
movzbl -0x29(%rbp),%eax
and    $0x7,%eax
cltq
mov    %rax,-0x28(%rbp)
jmp    1377 <isUTF8+0x277>
movzbl -0x29(%rbp),%eax
and    $0xfc,%eax
cmp    $0xf8,%eax
jne    1224 <isUTF8+0x124>
movl   $0x4,-0x20(%rbp)
movl   $0x4,-0x1c(%rbp)
movzbl -0x29(%rbp),%eax
and    $0x3,%eax
cltq
mov    %rax,-0x28(%rbp)
jmp    1377 <isUTF8+0x277>
movzbl -0x29(%rbp),%eax
and    $0xfe,%eax
cmp    $0xfc,%eax
jne    1258 <isUTF8+0x158>
movl   $0x5,-0x20(%rbp)
movl   $0x5,-0x1c(%rbp)
movzbl -0x29(%rbp),%eax
and    $0x1,%eax
cltq
mov    %rax,-0x28(%rbp)
jmp    1377 <isUTF8+0x277>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
movzbl -0x29(%rbp),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
je     1284 <isUTF8+0x184>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
mov    -0x28(%rbp),%rax
shl    $0x6,%rax
mov    %rax,-0x28(%rbp)
movzbl -0x29(%rbp),%eax
and    $0x3f,%eax
cltq
add    -0x28(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x1c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x1c(%rbp)
cmpl   $0x0,-0x1c(%rbp)
jne    136d <isUTF8+0x26d>
cmpl   $0x1,-0x20(%rbp)
jne    12d8 <isUTF8+0x1d8>
cmpq   $0x80,-0x28(%rbp)
jae    12d8 <isUTF8+0x1d8>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
cmpl   $0x2,-0x20(%rbp)
jne    12fc <isUTF8+0x1fc>
cmpq   $0x800,-0x28(%rbp)
jae    12fc <isUTF8+0x1fc>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
cmpl   $0x3,-0x20(%rbp)
jne    1320 <isUTF8+0x220>
cmpq   $0x10000,-0x28(%rbp)
jae    1320 <isUTF8+0x220>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
cmpl   $0x4,-0x20(%rbp)
jne    1344 <isUTF8+0x244>
cmpq   $0x200000,-0x28(%rbp)
jae    1344 <isUTF8+0x244>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
cmpl   $0x5,-0x20(%rbp)
jne    1368 <isUTF8+0x268>
cmpq   $0x4000000,-0x28(%rbp)
04
jae    1368 <isUTF8+0x268>
movl   $0x0,-0x4(%rbp)
jmp    138c <isUTF8+0x28c>
jmp    136d <isUTF8+0x26d>
jmp    1372 <isUTF8+0x272>
jmp    1377 <isUTF8+0x277>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1119 <isUTF8+0x19>
movl   $0x1,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<isUTF8>:
test   %esi,%esi
jle    1285 <isUTF8+0x185>
mov    %esi,%r8d
xor    %r11d,%r11d
xor    %esi,%esi
jmp    1131 <isUTF8+0x31>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mov    %esi,%eax
add    $0x1,%r11
mov    %eax,%esi
cmp    %r11,%r8
je     1285 <isUTF8+0x185>
movzbl (%rdi,%r11,1),%ecx
test   %esi,%esi
je     11d0 <isUTF8+0xd0>
mov    %ecx,%edx
and    $0xffffffc0,%edx
xor    %eax,%eax
cmp    $0x80,%edx
jne    128a <isUTF8+0x18a>
mov    %r10,%rdx
shl    $0x6,%rdx
and    $0x3f,%ecx
mov    %rcx,%r10
or     %rdx,%r10
add    $0xffffffff,%esi
jne    1120 <isUTF8+0x20>
cmp    $0x1,%r9d
jne    1179 <isUTF8+0x79>
cmp    $0x80,%r10
jb     128a <isUTF8+0x18a>
cmp    $0x2,%r9d
jne    118c <isUTF8+0x8c>
cmp    $0x800,%r10
jb     128a <isUTF8+0x18a>
cmp    $0x3,%r9d
jne    119f <isUTF8+0x9f>
cmp    $0x10000,%r10
jb     128a <isUTF8+0x18a>
cmp    $0x4,%r9d
jne    11b2 <isUTF8+0xb2>
cmp    $0x200000,%r10
jb     128a <isUTF8+0x18a>
xor    %eax,%eax
cmp    $0x5,%r9d
jne    1122 <isUTF8+0x22>
cmp    $0x4000000,%r10
jae    1122 <isUTF8+0x22>
jmp    128a <isUTF8+0x18a>
xor    %eax,%eax
test   $0x80,%cl
je     1122 <isUTF8+0x22>
mov    %ecx,%eax
and    $0xffffffe0,%eax
cmp    $0xc0,%eax
jne    11fd <isUTF8+0xfd>
and    $0x1f,%ecx
mov    $0x1,%eax
mov    $0x1,%r9d
mov    %rcx,%r10
jmp    1122 <isUTF8+0x22>
mov    %ecx,%eax
and    $0xfffffff0,%eax
cmp    $0xe0,%eax
jne    121f <isUTF8+0x11f>
and    $0xf,%ecx
mov    $0x2,%eax
mov    $0x2,%r9d
mov    %rcx,%r10
jmp    1122 <isUTF8+0x22>
mov    %ecx,%eax
and    $0xfffffff8,%eax
cmp    $0xf0,%eax
jne    1241 <isUTF8+0x141>
and    $0x7,%ecx
mov    $0x3,%eax
mov    $0x3,%r9d
mov    %rcx,%r10
jmp    1122 <isUTF8+0x22>
mov    %ecx,%eax
and    $0xfffffffc,%eax
cmp    $0xf8,%eax
jne    1263 <isUTF8+0x163>
and    $0x3,%ecx
mov    $0x4,%eax
mov    $0x4,%r9d
mov    %rcx,%r10
jmp    1122 <isUTF8+0x22>
mov    %ecx,%eax
and    $0xfffffffe,%eax
cmp    $0xfc,%eax
jne    128b <isUTF8+0x18b>
and    $0x1,%ecx
mov    $0x5,%eax
mov    $0x5,%r9d
mov    %rcx,%r10
jmp    1122 <isUTF8+0x22>
mov    $0x1,%eax
ret
xor    %eax,%eax
ret

LLVM IR (-O0):
define i32 @isUTF8(i8* %0, i32 %1) {
%3 = alloca i32
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i64
%10 = alloca i8
store i8* %0, i8** %4
store i32 %1, i32* %5
store i32 0, i32* %7
store i32 0, i32* %6
br label %11
11: ; preds = %137, %2
%12 = load i32, i32* %6
%13 = load i32, i32* %5
%14 = icmp slt i32 %12, %13
br i1 %14, label %15, label %140
15: ; preds = %11
%16 = load i8*, i8** %4
%17 = load i32, i32* %6
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds i8, i8* %16, i64 %18
%20 = load i8, i8* %19
store i8 %20, i8* %10
%21 = load i32, i32* %7
%22 = icmp eq i32 %21, 0
br i1 %22, label %23, label %80
23: ; preds = %15
%24 = load i8, i8* %10
%25 = zext i8 %24 to i32
%26 = and i32 %25, 128
%27 = icmp eq i32 %26, 0
br i1 %27, label %28, label %29
28: ; preds = %23
br label %137
29: ; preds = %23
%30 = load i8, i8* %10
%31 = zext i8 %30 to i32
%32 = and i32 %31, 224
%33 = icmp eq i32 %32, 192
br i1 %33, label %34, label %39
34: ; preds = %29
store i32 1, i32* %8
store i32 1, i32* %7
%35 = load i8, i8* %10
%36 = zext i8 %35 to i32
%37 = and i32 %36, 31
%38 = sext i32 %37 to i64
store i64 %38, i64* %9
br label %137
39: ; preds = %29
%40 = load i8, i8* %10
%41 = zext i8 %40 to i32
%42 = and i32 %41, 240
%43 = icmp eq i32 %42, 224
br i1 %43, label %44, label %49
44: ; preds = %39
store i32 2, i32* %8
store i32 2, i32* %7
%45 = load i8, i8* %10
%46 = zext i8 %45 to i32
%47 = and i32 %46, 15
%48 = sext i32 %47 to i64
store i64 %48, i64* %9
br label %137
49: ; preds = %39
%50 = load i8, i8* %10
%51 = zext i8 %50 to i32
%52 = and i32 %51, 248
%53 = icmp eq i32 %52, 240
br i1 %53, label %54, label %59
54: ; preds = %49
store i32 3, i32* %8
store i32 3, i32* %7
%55 = load i8, i8* %10
%56 = zext i8 %55 to i32
%57 = and i32 %56, 7
%58 = sext i32 %57 to i64
store i64 %58, i64* %9
br label %137
59: ; preds = %49
%60 = load i8, i8* %10
%61 = zext i8 %60 to i32
%62 = and i32 %61, 252
%63 = icmp eq i32 %62, 248
br i1 %63, label %64, label %69
64: ; preds = %59
store i32 4, i32* %8
store i32 4, i32* %7
%65 = load i8, i8* %10
%66 = zext i8 %65 to i32
%67 = and i32 %66, 3
%68 = sext i32 %67 to i64
store i64 %68, i64* %9
br label %137
69: ; preds = %59
%70 = load i8, i8* %10
%71 = zext i8 %70 to i32
%72 = and i32 %71, 254
%73 = icmp eq i32 %72, 252
br i1 %73, label %74, label %79
74: ; preds = %69
store i32 5, i32* %8
store i32 5, i32* %7
%75 = load i8, i8* %10
%76 = zext i8 %75 to i32
%77 = and i32 %76, 1
%78 = sext i32 %77 to i64
store i64 %78, i64* %9
br label %137
79: ; preds = %69
store i32 0, i32* %3
br label %141
80: ; preds = %15
%81 = load i8, i8* %10
%82 = zext i8 %81 to i32
%83 = and i32 %82, 192
%84 = icmp ne i32 %83, 128
br i1 %84, label %85, label %86
85: ; preds = %80
store i32 0, i32* %3
br label %141
86: ; preds = %80
%87 = load i64, i64* %9
%88 = shl i64 %87, 6
store i64 %88, i64* %9
%89 = load i8, i8* %10
%90 = zext i8 %89 to i32
%91 = and i32 %90, 63
%92 = sext i32 %91 to i64
%93 = load i64, i64* %9
%94 = add i64 %93, %92
store i64 %94, i64* %9
%95 = load i32, i32* %7
%96 = add nsw i32 %95, -1
store i32 %96, i32* %7
%97 = load i32, i32* %7
%98 = icmp ne i32 %97, 0
br i1 %98, label %135, label %99
99: ; preds = %86
%100 = load i32, i32* %8
%101 = icmp eq i32 %100, 1
br i1 %101, label %102, label %106
102: ; preds = %99
%103 = load i64, i64* %9
%104 = icmp ult i64 %103, 128
br i1 %104, label %105, label %106
105: ; preds = %102
store i32 0, i32* %3
br label %141
106: ; preds = %102, %99
%107 = load i32, i32* %8
%108 = icmp eq i32 %107, 2
br i1 %108, label %109, label %113
109: ; preds = %106
%110 = load i64, i64* %9
%111 = icmp ult i64 %110, 2048
br i1 %111, label %112, label %113
112: ; preds = %109
store i32 0, i32* %3
br label %141
113: ; preds = %109, %106
%114 = load i32, i32* %8
%115 = icmp eq i32 %114, 3
br i1 %115, label %116, label %120
116: ; preds = %113
%117 = load i64, i64* %9
%118 = icmp ult i64 %117, 65536
br i1 %118, label %119, label %120
119: ; preds = %116
store i32 0, i32* %3
br label %141
120: ; preds = %116, %113
%121 = load i32, i32* %8
%122 = icmp eq i32 %121, 4
br i1 %122, label %123, label %127
123: ; preds = %120
%124 = load i64, i64* %9
%125 = icmp ult i64 %124, 2097152
br i1 %125, label %126, label %127
126: ; preds = %123
store i32 0, i32* %3
br label %141
127: ; preds = %123, %120
%128 = load i32, i32* %8
%129 = icmp eq i32 %128, 5
br i1 %129, label %130, label %134
130: ; preds = %127
%131 = load i64, i64* %9
%132 = icmp ult i64 %131, 67108864
br i1 %132, label %133, label %134
133: ; preds = %130
store i32 0, i32* %3
br label %141
134: ; preds = %130, %127
br label %135
135: ; preds = %134, %86
br label %136
136: ; preds = %135
br label %137
137: ; preds = %136, %74, %64, %54, %44, %34, %28
%138 = load i32, i32* %6
%139 = add nsw i32 %138, 1
store i32 %139, i32* %6
br label %11
140: ; preds = %11
store i32 1, i32* %3
br label %141
141: ; preds = %140, %133, %126, %119, %112, %105, %85, %79
%142 = load i32, i32* %3
ret i32 %142
}

LLVM IR (-O2):
define i32 @isUTF8(i8* nocapture %0, i32 %1) {
%3 = icmp sgt i32 %1, 0
br i1 %3, label %4, label %84
4: ; preds = %2
%5 = zext i32 %1 to i64
br label %6
6: ; preds = %4, %78
%7 = phi i64 [ 0, %4 ], [ %82, %78 ]
%8 = phi i64 [ undef, %4 ], [ %81, %78 ]
%9 = phi i32 [ undef, %4 ], [ %80, %78 ]
%10 = phi i32 [ 0, %4 ], [ %79, %78 ]
%11 = getelementptr inbounds i8, i8* %0, i64 %7
%12 = load i8, i8* %11
%13 = icmp eq i32 %10, 0
%14 = zext i8 %12 to i32
br i1 %13, label %15, label %48
15: ; preds = %6
%16 = and i32 %14, 128
%17 = icmp eq i32 %16, 0
br i1 %17, label %78, label %18
18: ; preds = %15
%19 = and i32 %14, 224
%20 = icmp eq i32 %19, 192
br i1 %20, label %21, label %24
21: ; preds = %18
%22 = and i32 %14, 31
%23 = zext i32 %22 to i64
br label %78
24: ; preds = %18
%25 = and i32 %14, 240
%26 = icmp eq i32 %25, 224
br i1 %26, label %27, label %30
27: ; preds = %24
%28 = and i32 %14, 15
%29 = zext i32 %28 to i64
br label %78
30: ; preds = %24
%31 = and i32 %14, 248
%32 = icmp eq i32 %31, 240
br i1 %32, label %33, label %36
33: ; preds = %30
%34 = and i32 %14, 7
%35 = zext i32 %34 to i64
br label %78
36: ; preds = %30
%37 = and i32 %14, 252
%38 = icmp eq i32 %37, 248
br i1 %38, label %39, label %42
39: ; preds = %36
%40 = and i32 %14, 3
%41 = zext i32 %40 to i64
br label %78
42: ; preds = %36
%43 = and i32 %14, 254
%44 = icmp eq i32 %43, 252
br i1 %44, label %45, label %84
45: ; preds = %42
%46 = and i32 %14, 1
%47 = zext i32 %46 to i64
br label %78
48: ; preds = %6
%49 = and i32 %14, 192
%50 = icmp eq i32 %49, 128
br i1 %50, label %51, label %84
51: ; preds = %48
%52 = shl i64 %8, 6
%53 = and i32 %14, 63
%54 = zext i32 %53 to i64
%55 = or i64 %52, %54
%56 = add nsw i32 %10, -1
%57 = icmp eq i32 %56, 0
br i1 %57, label %58, label %78
58: ; preds = %51
%59 = icmp eq i32 %9, 1
%60 = icmp ult i64 %55, 128
%61 = select i1 %59, i1 %60, i1 false
br i1 %61, label %84, label %62
62: ; preds = %58
%63 = icmp eq i32 %9, 2
%64 = icmp ult i64 %55, 2048
%65 = select i1 %63, i1 %64, i1 false
br i1 %65, label %84, label %66
66: ; preds = %62
%67 = icmp eq i32 %9, 3
%68 = icmp ult i64 %55, 65536
%69 = select i1 %67, i1 %68, i1 false
br i1 %69, label %84, label %70
70: ; preds = %66
%71 = icmp eq i32 %9, 4
%72 = icmp ult i64 %55, 2097152
%73 = select i1 %71, i1 %72, i1 false
br i1 %73, label %84, label %74
74: ; preds = %70
%75 = icmp eq i32 %9, 5
%76 = icmp ult i64 %55, 67108864
%77 = select i1 %75, i1 %76, i1 false
br i1 %77, label %84, label %78
78: ; preds = %74, %51, %15, %45, %39, %33, %27, %21
%79 = phi i32 [ 0, %15 ], [ 1, %21 ], [ 2, %27 ], [ 3, %33 ], [ 4, %39 ], [ 5, %45 ], [ %56, %51 ], [ 0, %74 ]
%80 = phi i32 [ %9, %15 ], [ 1, %21 ], [ 2, %27 ], [ 3, %33 ], [ 4, %39 ], [ 5, %45 ], [ %9, %51 ], [ %9, %74 ]
%81 = phi i64 [ %8, %15 ], [ %23, %21 ], [ %29, %27 ], [ %35, %33 ], [ %41, %39 ], [ %47, %45 ], [ %55, %51 ], [ %55, %74 ]
%82 = add nuw nsw i64 %7, 1
%83 = icmp eq i64 %82, %5
br i1 %83, label %84, label %6
84: ; preds = %42, %48, %58, %62, %66, %70, %74, %78, %2
%85 = phi i32 [ 1, %2 ], [ 1, %78 ], [ 0, %74 ], [ 0, %70 ], [ 0, %66 ], [ 0, %62 ], [ 0, %58 ], [ 0, %48 ], [ 0, %42 ]
ret i32 %85
}