int utf8CharLen(short *unicode, int len) {
  int count = 1;
  for (; len > 0; len--) {
    short c = *unicode++;
    count += c > 0xf ? (c > 0x7ff ? 3 : 2) : 1;
  }
  return count;
}


x86 assembly (clang, -O0):
<utf8CharLen>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
movl   $0x1,-0x10(%rbp)
cmpl   $0x0,-0xc(%rbp)
jle    1182 <utf8CharLen+0x82>
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x2,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%ax
mov    %ax,-0x12(%rbp)
movswl -0x12(%rbp),%eax
cmp    $0xf,%eax
jle    115e <utf8CharLen+0x5e>
movswl -0x12(%rbp),%edx
mov    $0x2,%eax
mov    $0x3,%ecx
cmp    $0x7ff,%edx
cmovg  %ecx,%eax
mov    %eax,-0x18(%rbp)
jmp    116b <utf8CharLen+0x6b>
mov    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    116b <utf8CharLen+0x6b>
mov    -0x18(%rbp),%eax
add    -0x10(%rbp),%eax
mov    %eax,-0x10(%rbp)
mov    -0xc(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0xc(%rbp)
jmp    1112 <utf8CharLen+0x12>
mov    -0x10(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<utf8CharLen>:
test   %esi,%esi
jle    111e <utf8CharLen+0x1e>
lea    -0x1(%rsi),%r9d
mov    $0x1,%r11d
cmp    $0x7,%r9d
jae    1124 <utf8CharLen+0x24>
mov    $0x1,%eax
jmp    1331 <utf8CharLen+0x231>
mov    $0x1,%eax
ret
add    $0x1,%r9
mov    %r9,%r8
and    $0xfffffffffffffff8,%r8
lea    -0x8(%r8),%rax
mov    %rax,%r10
shr    $0x3,%r10
add    $0x1,%r10
test   %rax,%rax
je     1368 <utf8CharLen+0x268>
mov    %r10,%rax
and    $0xfffffffffffffffe,%rax
pxor   %xmm0,%xmm0
movdqa 0xea6(%rip),%xmm1
xor    %edx,%edx
movdqa 0xeab(%rip),%xmm8
movdqa 0xeb2(%rip),%xmm9
movdqa 0xeba(%rip),%xmm4
movdqa 0xec2(%rip),%xmm5
xchg   %ax,%ax
movq   (%rdi,%rdx,2),%xmm3
movq   0x8(%rdi,%rdx,2),%xmm2
movdqa %xmm3,%xmm6
pcmpgtw %xmm8,%xmm6
punpcklwd %xmm6,%xmm7
psrad  $0x10,%xmm7
movdqa %xmm2,%xmm6
pcmpgtw %xmm8,%xmm6
punpcklwd %xmm6,%xmm6
psrad  $0x10,%xmm6
pcmpgtw %xmm9,%xmm3
punpcklwd %xmm3,%xmm3
pand   %xmm4,%xmm3
por    %xmm5,%xmm3
pcmpgtw %xmm9,%xmm2
punpcklwd %xmm2,%xmm2
pand   %xmm4,%xmm2
por    %xmm5,%xmm2
pand   %xmm7,%xmm3
pandn  %xmm4,%xmm7
por    %xmm3,%xmm7
paddd  %xmm1,%xmm7
pand   %xmm6,%xmm2
pandn  %xmm4,%xmm6
por    %xmm2,%xmm6
paddd  %xmm0,%xmm6
movq   0x10(%rdi,%rdx,2),%xmm3
movq   0x18(%rdi,%rdx,2),%xmm2
movdqa %xmm3,%xmm0
pcmpgtw %xmm8,%xmm0
punpcklwd %xmm0,%xmm1
psrad  $0x10,%xmm1
movdqa %xmm2,%xmm0
pcmpgtw %xmm8,%xmm0
punpcklwd %xmm0,%xmm0
psrad  $0x10,%xmm0
pcmpgtw %xmm9,%xmm3
punpcklwd %xmm3,%xmm3
pand   %xmm4,%xmm3
por    %xmm5,%xmm3
pcmpgtw %xmm9,%xmm2
punpcklwd %xmm2,%xmm2
pand   %xmm4,%xmm2
por    %xmm5,%xmm2
pand   %xmm1,%xmm3
pandn  %xmm4,%xmm1
por    %xmm3,%xmm1
paddd  %xmm7,%xmm1
pand   %xmm0,%xmm2
pandn  %xmm4,%xmm0
por    %xmm2,%xmm0
paddd  %xmm6,%xmm0
add    $0x10,%rdx
add    $0xfffffffffffffffe,%rax
jne    1180 <utf8CharLen+0x80>
test   $0x1,%r10b
je     130b <utf8CharLen+0x20b>
movq   (%rdi,%rdx,2),%xmm3
movq   0x8(%rdi,%rdx,2),%xmm2
movdqa 0xd82(%rip),%xmm4
movdqa %xmm3,%xmm5
pcmpgtw %xmm4,%xmm5
punpcklwd %xmm5,%xmm5
psrad  $0x10,%xmm5
movdqa %xmm2,%xmm6
pcmpgtw %xmm4,%xmm6
punpcklwd %xmm6,%xmm4
psrad  $0x10,%xmm4
movdqa 0xd67(%rip),%xmm8
pcmpgtw %xmm8,%xmm3
punpcklwd %xmm3,%xmm3
movdqa 0xd66(%rip),%xmm7
pand   %xmm7,%xmm3
movdqa 0xd6a(%rip),%xmm6
por    %xmm6,%xmm3
pcmpgtw %xmm8,%xmm2
punpcklwd %xmm2,%xmm2
pand   %xmm7,%xmm2
por    %xmm6,%xmm2
pand   %xmm5,%xmm3
pandn  %xmm7,%xmm5
por    %xmm3,%xmm5
paddd  %xmm5,%xmm1
pand   %xmm4,%xmm2
pandn  %xmm7,%xmm4
por    %xmm2,%xmm4
paddd  %xmm4,%xmm0
paddd  %xmm0,%xmm1
pshufd $0xee,%xmm1,%xmm0
paddd  %xmm1,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddd  %xmm0,%xmm1
movd   %xmm1,%eax
cmp    %r8,%r9
je     1367 <utf8CharLen+0x267>
lea    (%rdi,%r8,2),%rdi
sub    %r8d,%esi
add    $0x1,%esi
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movswl (%rdi),%edx
add    $0x2,%rdi
xor    %ecx,%ecx
cmp    $0x800,%edx
setge  %cl
or     $0x2,%ecx
cmp    $0x10,%dx
cmovl  %r11d,%ecx
add    %ecx,%eax
add    $0xffffffff,%esi
cmp    $0x1,%esi
ja     1340 <utf8CharLen+0x240>
ret
pxor   %xmm0,%xmm0
movdqa 0xc8c(%rip),%xmm1
xor    %edx,%edx
test   $0x1,%r10b
jne    127b <utf8CharLen+0x17b>
jmp    130b <utf8CharLen+0x20b>

LLVM IR (-O0):
define i32 @utf8CharLen(i16* %0, i32 %1) {
%3 = alloca i16*
%4 = alloca i32
%5 = alloca i32
%6 = alloca i16
store i16* %0, i16** %3
store i32 %1, i32* %4
store i32 1, i32* %5
br label %7
7: ; preds = %28, %2
%8 = load i32, i32* %4
%9 = icmp sgt i32 %8, 0
br i1 %9, label %10, label %31
10: ; preds = %7
%11 = load i16*, i16** %3
%12 = getelementptr inbounds i16, i16* %11, i32 1
store i16* %12, i16** %3
%13 = load i16, i16* %11
store i16 %13, i16* %6
%14 = load i16, i16* %6
%15 = sext i16 %14 to i32
%16 = icmp sgt i32 %15, 15
br i1 %16, label %17, label %23
17: ; preds = %10
%18 = load i16, i16* %6
%19 = sext i16 %18 to i32
%20 = icmp sgt i32 %19, 2047
%21 = zext i1 %20 to i64
%22 = select i1 %20, i32 3, i32 2
br label %24
23: ; preds = %10
br label %24
24: ; preds = %23, %17
%25 = phi i32 [ %22, %17 ], [ 1, %23 ]
%26 = load i32, i32* %5
%27 = add nsw i32 %26, %25
store i32 %27, i32* %5
br label %28
28: ; preds = %24
%29 = load i32, i32* %4
%30 = add nsw i32 %29, -1
store i32 %30, i32* %4
br label %7
31: ; preds = %7
%32 = load i32, i32* %5
ret i32 %32
}

LLVM IR (-O2):
define i32 @utf8CharLen(i16* nocapture %0, i32 %1) {
%3 = icmp sgt i32 %1, 0
br i1 %3, label %4, label %109
4: ; preds = %2
%5 = add i32 %1, -1
%6 = zext i32 %5 to i64
%7 = add nuw nsw i64 %6, 1
%8 = icmp ult i32 %5, 7
br i1 %8, label %92, label %9
9: ; preds = %4
%10 = and i64 %7, 8589934584
%11 = getelementptr i16, i16* %0, i64 %10
%12 = trunc i64 %10 to i32
%13 = sub i32 %1, %12
%14 = add nsw i64 %10, -8
%15 = lshr exact i64 %14, 3
%16 = add nuw nsw i64 %15, 1
%17 = and i64 %16, 1
%18 = icmp eq i64 %14, 0
br i1 %18, label %62, label %19
19: ; preds = %9
%20 = and i64 %16, 4611686018427387902
br label %21
21: ; preds = %21, %19
%22 = phi i64 [ 0, %19 ], [ %59, %21 ]
%23 = phi <4 x i32> [ <i32 1, i32 0, i32 0, i32 0>, %19 ], [ %57, %21 ]
%24 = phi <4 x i32> [ zeroinitializer, %19 ], [ %58, %21 ]
%25 = phi i64 [ 0, %19 ], [ %60, %21 ]
%26 = getelementptr i16, i16* %0, i64 %22
%27 = bitcast i16* %26 to <4 x i16>*
%28 = load <4 x i16>, <4 x i16>* %27
%29 = getelementptr i16, i16* %26, i64 4
%30 = bitcast i16* %29 to <4 x i16>*
%31 = load <4 x i16>, <4 x i16>* %30
%32 = icmp sgt <4 x i16> %28, <i16 15, i16 15, i16 15, i16 15>
%33 = icmp sgt <4 x i16> %31, <i16 15, i16 15, i16 15, i16 15>
%34 = icmp sgt <4 x i16> %28, <i16 2047, i16 2047, i16 2047, i16 2047>
%35 = icmp sgt <4 x i16> %31, <i16 2047, i16 2047, i16 2047, i16 2047>
%36 = select <4 x i1> %34, <4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
%37 = select <4 x i1> %35, <4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
%38 = select <4 x i1> %32, <4 x i32> %36, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%39 = select <4 x i1> %33, <4 x i32> %37, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%40 = add <4 x i32> %38, %23
%41 = add <4 x i32> %39, %24
%42 = or i64 %22, 8
%43 = getelementptr i16, i16* %0, i64 %42
%44 = bitcast i16* %43 to <4 x i16>*
%45 = load <4 x i16>, <4 x i16>* %44
%46 = getelementptr i16, i16* %43, i64 4
%47 = bitcast i16* %46 to <4 x i16>*
%48 = load <4 x i16>, <4 x i16>* %47
%49 = icmp sgt <4 x i16> %45, <i16 15, i16 15, i16 15, i16 15>
%50 = icmp sgt <4 x i16> %48, <i16 15, i16 15, i16 15, i16 15>
%51 = icmp sgt <4 x i16> %45, <i16 2047, i16 2047, i16 2047, i16 2047>
%52 = icmp sgt <4 x i16> %48, <i16 2047, i16 2047, i16 2047, i16 2047>
%53 = select <4 x i1> %51, <4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
%54 = select <4 x i1> %52, <4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
%55 = select <4 x i1> %49, <4 x i32> %53, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%56 = select <4 x i1> %50, <4 x i32> %54, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%57 = add <4 x i32> %55, %40
%58 = add <4 x i32> %56, %41
%59 = add nuw i64 %22, 16
%60 = add i64 %25, 2
%61 = icmp eq i64 %60, %20
br i1 %61, label %62, label %21
62: ; preds = %21, %9
%63 = phi <4 x i32> [ undef, %9 ], [ %57, %21 ]
%64 = phi <4 x i32> [ undef, %9 ], [ %58, %21 ]
%65 = phi i64 [ 0, %9 ], [ %59, %21 ]
%66 = phi <4 x i32> [ <i32 1, i32 0, i32 0, i32 0>, %9 ], [ %57, %21 ]
%67 = phi <4 x i32> [ zeroinitializer, %9 ], [ %58, %21 ]
%68 = icmp eq i64 %17, 0
br i1 %68, label %86, label %69
69: ; preds = %62
%70 = getelementptr i16, i16* %0, i64 %65
%71 = bitcast i16* %70 to <4 x i16>*
%72 = load <4 x i16>, <4 x i16>* %71
%73 = getelementptr i16, i16* %70, i64 4
%74 = bitcast i16* %73 to <4 x i16>*
%75 = load <4 x i16>, <4 x i16>* %74
%76 = icmp sgt <4 x i16> %72, <i16 15, i16 15, i16 15, i16 15>
%77 = icmp sgt <4 x i16> %75, <i16 15, i16 15, i16 15, i16 15>
%78 = icmp sgt <4 x i16> %72, <i16 2047, i16 2047, i16 2047, i16 2047>
%79 = icmp sgt <4 x i16> %75, <i16 2047, i16 2047, i16 2047, i16 2047>
%80 = select <4 x i1> %78, <4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
%81 = select <4 x i1> %79, <4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
%82 = select <4 x i1> %76, <4 x i32> %80, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%83 = select <4 x i1> %77, <4 x i32> %81, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%84 = add <4 x i32> %82, %66
%85 = add <4 x i32> %83, %67
br label %86
86: ; preds = %62, %69
%87 = phi <4 x i32> [ %63, %62 ], [ %84, %69 ]
%88 = phi <4 x i32> [ %64, %62 ], [ %85, %69 ]
%89 = add <4 x i32> %88, %87
%90 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %89)
%91 = icmp eq i64 %7, %10
br i1 %91, label %109, label %92
92: ; preds = %4, %86
%93 = phi i16* [ %0, %4 ], [ %11, %86 ]
%94 = phi i32 [ 1, %4 ], [ %90, %86 ]
%95 = phi i32 [ %1, %4 ], [ %13, %86 ]
br label %96
96: ; preds = %92, %96
%97 = phi i16* [ %100, %96 ], [ %93, %92 ]
%98 = phi i32 [ %106, %96 ], [ %94, %92 ]
%99 = phi i32 [ %107, %96 ], [ %95, %92 ]
%100 = getelementptr inbounds i16, i16* %97, i64 1
%101 = load i16, i16* %97
%102 = icmp sgt i16 %101, 15
%103 = icmp sgt i16 %101, 2047
%104 = select i1 %103, i32 3, i32 2
%105 = select i1 %102, i32 %104, i32 1
%106 = add nuw nsw i32 %105, %98
%107 = add nsw i32 %99, -1
%108 = icmp ugt i32 %99, 1
br i1 %108, label %96, label %109
109: ; preds = %96, %86, %2
%110 = phi i32 [ 1, %2 ], [ %90, %86 ], [ %106, %96 ]
ret i32 %110
}