#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef char uint32_t;

/* Variables and functions */
uint32_t UTF16BytesNeededForUTF8String(char *utf8str) {
  uint32_t needed = 2;
  while (*utf8str) {
    char a = *utf8str;
    uint32_t codepoint;
    if ((a & 0x80) == 0) {
      codepoint = a;
    } else if ((a & 0xE0) == 0xC0) {
      codepoint = (a & 0x1F) << 6;
      a = *(utf8str++);
      codepoint |= (a & 0x3F);
    } else if ((a & 0xF0) == 0xE0) {
      codepoint = (a & 0x0F) << 12;
      a = *(utf8str++);
      codepoint |= (a & 0x3F) << 6;
      a = *(utf8str++);
      codepoint |= (a & 0x3F);
    } else if ((a & 0xF8) == 0xF0) {
      codepoint = (a & 0x07) << 18;
      a = *(utf8str++);
      codepoint |= (a & 0x3F) << 12;
      a = *(utf8str++);
      codepoint |= (a & 0x3F) << 6;
      a = *(utf8str++);
      codepoint |= (a & 0x3F);
    } else {
      continue;
    }
    if (codepoint <= 0xD7FF) {
      needed += 2;
    } else if (codepoint >= 0x10000) {
      needed += 4;
    }
  }
  return needed;
}


x86 assembly (clang, -O0):
<UTF16BytesNeededForUTF8String>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movb   $0x2,-0x9(%rbp)
mov    -0x8(%rbp),%rax
cmpb   $0x0,(%rax)
je     12e7 <UTF16BytesNeededForUTF8String+0x1e7>
mov    -0x8(%rbp),%rax
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
jne    113f <UTF16BytesNeededForUTF8String+0x3f>
mov    -0xa(%rbp),%al
mov    %al,-0xb(%rbp)
jmp    12a6 <UTF16BytesNeededForUTF8String+0x1a6>
movsbl -0xa(%rbp),%eax
and    $0xe0,%eax
cmp    $0xc0,%eax
jne    1189 <UTF16BytesNeededForUTF8String+0x89>
movsbl -0xa(%rbp),%eax
and    $0x1f,%eax
shl    $0x6,%eax
mov    %al,-0xb(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%ecx
and    $0x3f,%ecx
movsbl -0xb(%rbp),%eax
or     %ecx,%eax
mov    %al,-0xb(%rbp)
jmp    12a1 <UTF16BytesNeededForUTF8String+0x1a1>
movsbl -0xa(%rbp),%eax
and    $0xf0,%eax
cmp    $0xe0,%eax
jne    11fa <UTF16BytesNeededForUTF8String+0xfa>
movsbl -0xa(%rbp),%eax
and    $0xf,%eax
shl    $0xc,%eax
mov    %al,-0xb(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%ecx
and    $0x3f,%ecx
shl    $0x6,%ecx
movsbl -0xb(%rbp),%eax
or     %ecx,%eax
mov    %al,-0xb(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%ecx
and    $0x3f,%ecx
movsbl -0xb(%rbp),%eax
or     %ecx,%eax
mov    %al,-0xb(%rbp)
jmp    129c <UTF16BytesNeededForUTF8String+0x19c>
movsbl -0xa(%rbp),%eax
and    $0xf8,%eax
cmp    $0xf0,%eax
jne    1292 <UTF16BytesNeededForUTF8String+0x192>
movsbl -0xa(%rbp),%eax
and    $0x7,%eax
shl    $0x12,%eax
mov    %al,-0xb(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%ecx
and    $0x3f,%ecx
shl    $0xc,%ecx
movsbl -0xb(%rbp),%eax
or     %ecx,%eax
mov    %al,-0xb(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%ecx
and    $0x3f,%ecx
shl    $0x6,%ecx
movsbl -0xb(%rbp),%eax
or     %ecx,%eax
mov    %al,-0xb(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%ecx
and    $0x3f,%ecx
movsbl -0xb(%rbp),%eax
or     %ecx,%eax
mov    %al,-0xb(%rbp)
jmp    1297 <UTF16BytesNeededForUTF8String+0x197>
jmp    110c <UTF16BytesNeededForUTF8String+0xc>
jmp    129c <UTF16BytesNeededForUTF8String+0x19c>
jmp    12a1 <UTF16BytesNeededForUTF8String+0x1a1>
jmp    12a6 <UTF16BytesNeededForUTF8String+0x1a6>
movsbl -0xb(%rbp),%eax
cmp    $0xd7ff,%eax
jg     12c4 <UTF16BytesNeededForUTF8String+0x1c4>
movsbl -0x9(%rbp),%eax
add    $0x2,%eax
mov    %al,-0x9(%rbp)
jmp    12e2 <UTF16BytesNeededForUTF8String+0x1e2>
movsbl -0xb(%rbp),%eax
cmp    $0x10000,%eax
jl     12dd <UTF16BytesNeededForUTF8String+0x1dd>
movsbl -0x9(%rbp),%eax
add    $0x4,%eax
mov    %al,-0x9(%rbp)
jmp    12e2 <UTF16BytesNeededForUTF8String+0x1e2>
jmp    110c <UTF16BytesNeededForUTF8String+0xc>
movsbl -0x9(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<UTF16BytesNeededForUTF8String>:
mov    (%rdi),%cl
mov    $0x2,%al
jmp    1119 <UTF16BytesNeededForUTF8String+0x19>
cs nopw 0x0(%rax,%rax,1)
add    $0x1,%rdi
add    $0x2,%al
movzbl (%rdi),%ecx
test   %cl,%cl
je     1156 <UTF16BytesNeededForUTF8String+0x56>
test   $0x80,%cl
je     1114 <UTF16BytesNeededForUTF8String+0x14>
movzbl %cl,%edx
mov    %edx,%esi
and    $0xffffffe0,%esi
cmp    $0xc0,%esi
je     1110 <UTF16BytesNeededForUTF8String+0x10>
mov    %edx,%esi
and    $0xfffffff0,%esi
cmp    $0xe0,%esi
jne    1145 <UTF16BytesNeededForUTF8String+0x45>
add    $0x2,%rdi
jmp    1114 <UTF16BytesNeededForUTF8String+0x14>
and    $0xfffffff8,%edx
cmp    $0xf0,%edx
jne    1119 <UTF16BytesNeededForUTF8String+0x19>
add    $0x3,%rdi
jmp    1114 <UTF16BytesNeededForUTF8String+0x14>
ret

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

LLVM IR (-O2):
define signext i8 @UTF16BytesNeededForUTF8String(i8* nocapture %0) {
%2 = load i8, i8* %0
%3 = icmp eq i8 %2, 0
br i1 %3, label %35, label %4
4: ; preds = %1, %30
%5 = phi i8 [ %31, %30 ], [ %2, %1 ]
%6 = phi i8 [ %33, %30 ], [ 2, %1 ]
%7 = phi i8* [ %32, %30 ], [ %0, %1 ]
%8 = zext i8 %5 to i32
%9 = and i32 %8, 128
%10 = icmp eq i32 %9, 0
br i1 %10, label %26, label %11
11: ; preds = %4
%12 = and i32 %8, 224
%13 = icmp eq i32 %12, 192
br i1 %13, label %14, label %16
14: ; preds = %11
%15 = getelementptr inbounds i8, i8* %7, i64 1
br label %26
16: ; preds = %11
%17 = and i32 %8, 240
%18 = icmp eq i32 %17, 224
br i1 %18, label %19, label %21
19: ; preds = %16
%20 = getelementptr inbounds i8, i8* %7, i64 2
br label %26
21: ; preds = %16
%22 = and i32 %8, 248
%23 = icmp eq i32 %22, 240
br i1 %23, label %24, label %30
24: ; preds = %21
%25 = getelementptr inbounds i8, i8* %7, i64 3
br label %26
26: ; preds = %4, %14, %24, %19
%27 = phi i8* [ %15, %14 ], [ %20, %19 ], [ %25, %24 ], [ %7, %4 ]
%28 = add i8 %6, 2
%29 = load i8, i8* %27
br label %30
30: ; preds = %21, %26
%31 = phi i8 [ %29, %26 ], [ %5, %21 ]
%32 = phi i8* [ %27, %26 ], [ %7, %21 ]
%33 = phi i8 [ %28, %26 ], [ %6, %21 ]
%34 = icmp eq i8 %31, 0
br i1 %34, label %35, label %4
35: ; preds = %30, %1
%36 = phi i8 [ 2, %1 ], [ %33, %30 ]
ret i8 %36
}