int modifiedUtf8LengthOfUtf8(char *string, int length) {
  int new_length;
  int i;
  new_length = 0;
  for (i = 0; i < length && new_length >= 0; i++) {
    unsigned byte;
    byte = (unsigned char)string[i];
    if ((byte & 0x80) == 0) {
      new_length++;
      if (byte == 0) {
        new_length++;
      }
    } else if ((byte & 0xE0) == 0xC0) {
      if ((i + 1) >= length || (string[i + 1] & 0xC0) != 0x80) {
        break;
      }
      i++;
      new_length += 2;
    } else if ((byte & 0xF0) == 0xE0) {
      if ((i + 2) >= length || (string[i + 1] & 0xC0) != 0x80 ||
          (string[i + 2] & 0xC0) != 0x80) {
        break;
      }
      i += 2;
      new_length += 3;
    } else if ((byte & 0xF8) == 0xF0) {
      if ((i + 3) >= length || (string[i + 1] & 0xC0) != 0x80 ||
          (string[i + 2] & 0xC0) != 0x80 || (string[i + 3] & 0xC0) != 0x80) {
        break;
      }
      i += 3;
      new_length += 6;
    } else {
      break;
    }
  }
  if (i != length) {
    return length;
  }
  return new_length;
}


x86 assembly (clang, -O0):
<modifiedUtf8LengthOfUtf8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%ecx
xor    %eax,%eax
cmp    -0x14(%rbp),%ecx
mov    %al,-0x21(%rbp)
jge    1134 <modifiedUtf8LengthOfUtf8+0x34>
cmpl   $0x0,-0x18(%rbp)
setge  %al
mov    %al,-0x21(%rbp)
mov    -0x21(%rbp),%al
test   $0x1,%al
jne    1144 <modifiedUtf8LengthOfUtf8+0x44>
jmp    132c <modifiedUtf8LengthOfUtf8+0x22c>
mov    -0x10(%rbp),%rax
movslq -0x1c(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x20(%rbp)
mov    -0x20(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
jne    1185 <modifiedUtf8LengthOfUtf8+0x85>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
cmpl   $0x0,-0x20(%rbp)
jne    1180 <modifiedUtf8LengthOfUtf8+0x80>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1319 <modifiedUtf8LengthOfUtf8+0x219>
mov    -0x20(%rbp),%eax
and    $0xe0,%eax
cmp    $0xc0,%eax
jne    11e4 <modifiedUtf8LengthOfUtf8+0xe4>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
cmp    -0x14(%rbp),%eax
jge    11c8 <modifiedUtf8LengthOfUtf8+0xc8>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
je     11cd <modifiedUtf8LengthOfUtf8+0xcd>
jmp    132c <modifiedUtf8LengthOfUtf8+0x22c>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
mov    -0x18(%rbp),%eax
add    $0x2,%eax
mov    %eax,-0x18(%rbp)
jmp    1314 <modifiedUtf8LengthOfUtf8+0x214>
mov    -0x20(%rbp),%eax
and    $0xf0,%eax
cmp    $0xe0,%eax
jne    1264 <modifiedUtf8LengthOfUtf8+0x164>
mov    -0x1c(%rbp),%eax
add    $0x2,%eax
cmp    -0x14(%rbp),%eax
jge    1248 <modifiedUtf8LengthOfUtf8+0x148>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
jne    1248 <modifiedUtf8LengthOfUtf8+0x148>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
je     124d <modifiedUtf8LengthOfUtf8+0x14d>
jmp    132c <modifiedUtf8LengthOfUtf8+0x22c>
mov    -0x1c(%rbp),%eax
add    $0x2,%eax
mov    %eax,-0x1c(%rbp)
mov    -0x18(%rbp),%eax
add    $0x3,%eax
mov    %eax,-0x18(%rbp)
jmp    130f <modifiedUtf8LengthOfUtf8+0x20f>
mov    -0x20(%rbp),%eax
and    $0xf8,%eax
cmp    $0xf0,%eax
jne    1305 <modifiedUtf8LengthOfUtf8+0x205>
mov    -0x1c(%rbp),%eax
add    $0x3,%eax
cmp    -0x14(%rbp),%eax
jge    12e9 <modifiedUtf8LengthOfUtf8+0x1e9>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
jne    12e9 <modifiedUtf8LengthOfUtf8+0x1e9>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
jne    12e9 <modifiedUtf8LengthOfUtf8+0x1e9>
mov    -0x10(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x80,%eax
je     12ee <modifiedUtf8LengthOfUtf8+0x1ee>
jmp    132c <modifiedUtf8LengthOfUtf8+0x22c>
mov    -0x1c(%rbp),%eax
add    $0x3,%eax
mov    %eax,-0x1c(%rbp)
mov    -0x18(%rbp),%eax
add    $0x6,%eax
mov    %eax,-0x18(%rbp)
jmp    130a <modifiedUtf8LengthOfUtf8+0x20a>
jmp    132c <modifiedUtf8LengthOfUtf8+0x22c>
jmp    130f <modifiedUtf8LengthOfUtf8+0x20f>
jmp    1314 <modifiedUtf8LengthOfUtf8+0x214>
jmp    1319 <modifiedUtf8LengthOfUtf8+0x219>
jmp    131e <modifiedUtf8LengthOfUtf8+0x21e>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1119 <modifiedUtf8LengthOfUtf8+0x19>
mov    -0x1c(%rbp),%eax
cmp    -0x14(%rbp),%eax
je     1343 <modifiedUtf8LengthOfUtf8+0x243>
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1349 <modifiedUtf8LengthOfUtf8+0x249>
mov    -0x18(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<modifiedUtf8LengthOfUtf8>:
test   %esi,%esi
jle    11f2 <modifiedUtf8LengthOfUtf8+0xf2>
xor    %r9d,%r9d
xor    %eax,%eax
jmp    1126 <modifiedUtf8LengthOfUtf8+0x26>
nop
cmp    $0x1,%edx
adc    $0x0,%eax
add    $0x1,%eax
add    $0x1,%r9d
cmp    %esi,%r9d
jge    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movslq %r9d,%r10
movzbl (%rdi,%r10,1),%edx
test   $0x80,%dl
je     1110 <modifiedUtf8LengthOfUtf8+0x10>
mov    %edx,%ecx
and    $0xffffffe0,%ecx
cmp    $0xc0,%ecx
jne    1170 <modifiedUtf8LengthOfUtf8+0x70>
add    $0x1,%r10
cmp    %esi,%r10d
jge    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movzbl (%rdi,%r10,1),%ecx
and    $0xc0,%cl
cmp    $0x80,%cl
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
add    $0x2,%eax
mov    %r10d,%r9d
jmp    1119 <modifiedUtf8LengthOfUtf8+0x19>
cs nopw 0x0(%rax,%rax,1)
mov    %edx,%ecx
and    $0xfffffff0,%ecx
cmp    $0xe0,%ecx
jne    11aa <modifiedUtf8LengthOfUtf8+0xaa>
lea    0x2(%r10),%rcx
cmp    %esi,%ecx
jge    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movzbl 0x1(%r10,%rdi,1),%edx
and    $0xc0,%dl
cmp    $0x80,%dl
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movzbl (%rdi,%rcx,1),%edx
and    $0xc0,%dl
cmp    $0x80,%dl
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
add    $0x3,%eax
mov    %ecx,%r9d
jmp    1119 <modifiedUtf8LengthOfUtf8+0x19>
and    $0xfffffff8,%edx
cmp    $0xf0,%edx
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
lea    0x3(%r10),%r8
cmp    %esi,%r8d
jge    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movzbl 0x1(%r10,%rdi,1),%ecx
and    $0xc0,%cl
cmp    $0x80,%cl
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movzbl 0x2(%r10,%rdi,1),%ecx
and    $0xc0,%cl
cmp    $0x80,%cl
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
movzbl (%rdi,%r8,1),%ecx
and    $0xc0,%cl
cmp    $0x80,%cl
jne    11f7 <modifiedUtf8LengthOfUtf8+0xf7>
add    $0x6,%eax
mov    %r8d,%r9d
jmp    1119 <modifiedUtf8LengthOfUtf8+0x19>
xor    %eax,%eax
xor    %r9d,%r9d
cmp    %esi,%r9d
cmovne %esi,%eax
ret

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

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