#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 */

/* Variables and functions */
int /*<<< orphan*/ strrev(char *);
void strrev_utf8(char *p) {
  char *q = p;
  strrev(p);
  while (q && *q)
    ++q;
  while (p < --q)
    switch ((*q & 0xF0) >> 4) {
    case 0xF:
      (*(q - 0) ^= *(q - 3), *(q - 3) ^= *(q - 0), *(q - 0) ^= *(q - 3));
      (*(q - 1) ^= *(q - 2), *(q - 2) ^= *(q - 1), *(q - 1) ^= *(q - 2));
      q -= 3;
      break;
    case 0xE:
      (*(q - 0) ^= *(q - 2), *(q - 2) ^= *(q - 0), *(q - 0) ^= *(q - 2));
      q -= 2;
      break;
    case 0xC:
    case 0xD:
      (*(q - 0) ^= *(q - 1), *(q - 1) ^= *(q - 0), *(q - 0) ^= *(q - 1));
      q--;
      break;
    }
}


x86 assembly (clang, -O0):
<strrev_utf8>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x10(%rbp)
mov    -0x8(%rbp),%rdi
call   1030 <strrev@plt>
xor    %eax,%eax
cmpq   $0x0,-0x10(%rbp)
mov    %al,-0x11(%rbp)
je     114d <strrev_utf8+0x3d>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
setne  %al
mov    %al,-0x11(%rbp)
mov    -0x11(%rbp),%al
test   $0x1,%al
jne    115d <strrev_utf8+0x4d>
jmp    116e <strrev_utf8+0x5e>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
jmp    112d <strrev_utf8+0x1d>
jmp    1173 <strrev_utf8+0x63>
mov    -0x8(%rbp),%rax
mov    -0x10(%rbp),%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x10(%rbp)
cmp    %rcx,%rax
jae    12ec <strrev_utf8+0x1dc>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
shr    $0x4,%eax
mov    %eax,-0x18(%rbp)
add    $0xfffffff4,%eax
sub    $0x2,%eax
jb     12a1 <strrev_utf8+0x191>
jmp    11aa <strrev_utf8+0x9a>
mov    -0x18(%rbp),%eax
sub    $0xe,%eax
je     1256 <strrev_utf8+0x146>
jmp    11bb <strrev_utf8+0xab>
mov    -0x18(%rbp),%eax
sub    $0xf,%eax
jne    12e7 <strrev_utf8+0x1d7>
jmp    11cc <strrev_utf8+0xbc>
mov    -0x10(%rbp),%rax
movsbl -0x3(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %edx,%ecx
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
movsbl (%rax),%edx
mov    -0x10(%rbp),%rax
movsbl -0x3(%rax),%ecx
xor    %edx,%ecx
mov    %cl,-0x3(%rax)
mov    -0x10(%rbp),%rax
movsbl -0x3(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %edx,%ecx
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
movsbl -0x2(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl -0x1(%rax),%ecx
xor    %edx,%ecx
mov    %cl,-0x1(%rax)
mov    -0x10(%rbp),%rax
movsbl -0x1(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl -0x2(%rax),%ecx
xor    %edx,%ecx
mov    %cl,-0x2(%rax)
mov    -0x10(%rbp),%rax
movsbl -0x2(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl -0x1(%rax),%ecx
xor    %edx,%ecx
mov    %cl,-0x1(%rax)
mov    -0x10(%rbp),%rax
add    $0xfffffffffffffffd,%rax
mov    %rax,-0x10(%rbp)
jmp    12e7 <strrev_utf8+0x1d7>
mov    -0x10(%rbp),%rax
movsbl -0x2(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %edx,%ecx
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
movsbl (%rax),%edx
mov    -0x10(%rbp),%rax
movsbl -0x2(%rax),%ecx
xor    %edx,%ecx
mov    %cl,-0x2(%rax)
mov    -0x10(%rbp),%rax
movsbl -0x2(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %edx,%ecx
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
add    $0xfffffffffffffffe,%rax
mov    %rax,-0x10(%rbp)
jmp    12e7 <strrev_utf8+0x1d7>
mov    -0x10(%rbp),%rax
movsbl -0x1(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %edx,%ecx
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
movsbl (%rax),%edx
mov    -0x10(%rbp),%rax
movsbl -0x1(%rax),%ecx
xor    %edx,%ecx
mov    %cl,-0x1(%rax)
mov    -0x10(%rbp),%rax
movsbl -0x1(%rax),%edx
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %edx,%ecx
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x10(%rbp)
jmp    1173 <strrev_utf8+0x63>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<strrev_utf8>:
push   %r14
push   %rbx
push   %rax
mov    %rdi,%r14
call   1030 <strrev@plt>
test   %r14,%r14
je     113f <strrev_utf8+0x2f>
lea    -0x1(%r14),%rcx
cs nopw 0x0(%rax,%rax,1)
nop
lea    0x1(%rcx),%rax
cmpb   $0x0,0x1(%rcx)
mov    %rax,%rcx
jne    1130 <strrev_utf8+0x20>
jmp    1141 <strrev_utf8+0x31>
xor    %eax,%eax
lea    -0x1(%rax),%rcx
jmp    1164 <strrev_utf8+0x54>
nopw   0x0(%rax,%rax,1)
movzbl -0x2(%rax),%ebx
mov    %dl,-0x2(%rax)
mov    %bl,(%rcx)
lea    -0x2(%rax),%rcx
mov    %rcx,%rax
add    $0xffffffffffffffff,%rcx
cmp    %r14,%rcx
jbe    11a7 <strrev_utf8+0x97>
movzbl -0x1(%rax),%edx
mov    %edx,%esi
shr    $0x4,%esi
lea    -0xc(%rsi),%edi
cmp    $0x2,%edi
jb     1150 <strrev_utf8+0x40>
cmp    $0xe,%esi
je     1198 <strrev_utf8+0x88>
cmp    $0xf,%esi
jne    115d <strrev_utf8+0x4d>
movzbl -0x4(%rax),%ebx
mov    %dl,-0x4(%rax)
mov    %bl,(%rcx)
lea    -0x4(%rax),%rcx
rolw   $0x8,-0x3(%rax)
jmp    115d <strrev_utf8+0x4d>
movzbl -0x3(%rax),%ebx
mov    %dl,-0x3(%rax)
mov    %bl,(%rcx)
lea    -0x3(%rax),%rcx
jmp    115d <strrev_utf8+0x4d>
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret

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

LLVM IR (-O2):
define void @strrev_utf8(i8* %0) {
%2 = tail call i32 @strrev(i8* %0)
%3 = icmp eq i8* %0, null
br i1 %3, label %9, label %4
4: ; preds = %1, %4
%5 = phi i8* [ %8, %4 ], [ %0, %1 ]
%6 = load i8, i8* %5
%7 = icmp eq i8 %6, 0
%8 = getelementptr inbounds i8, i8* %5, i64 1
br i1 %7, label %9, label %4
9: ; preds = %4, %1
%10 = phi i8* [ null, %1 ], [ %5, %4 ]
%11 = getelementptr inbounds i8, i8* %10, i64 -1
%12 = icmp ugt i8* %11, %0
br i1 %12, label %13, label %36
13: ; preds = %9, %32
%14 = phi i8* [ %34, %32 ], [ %11, %9 ]
%15 = phi i8* [ %33, %32 ], [ %10, %9 ]
%16 = load i8, i8* %14
%17 = lshr i8 %16, 4
%18 = zext i8 %17 to i32
switch i32 %18, label %32 [
i32 15, label %19
i32 14, label %26
i32 12, label %29
i32 13, label %29
]
19: ; preds = %13
%20 = getelementptr inbounds i8, i8* %15, i64 -4
%21 = load i8, i8* %20
store i8 %16, i8* %20
store i8 %21, i8* %14
%22 = getelementptr inbounds i8, i8* %15, i64 -3
%23 = load i8, i8* %22
%24 = getelementptr inbounds i8, i8* %15, i64 -2
%25 = load i8, i8* %24
store i8 %25, i8* %22
store i8 %23, i8* %24
br label %32
26: ; preds = %13
%27 = getelementptr inbounds i8, i8* %15, i64 -3
%28 = load i8, i8* %27
store i8 %16, i8* %27
store i8 %28, i8* %14
br label %32
29: ; preds = %13, %13
%30 = getelementptr inbounds i8, i8* %15, i64 -2
%31 = load i8, i8* %30
store i8 %16, i8* %30
store i8 %31, i8* %14
br label %32
32: ; preds = %13, %29, %26, %19
%33 = phi i8* [ %14, %13 ], [ %30, %29 ], [ %27, %26 ], [ %20, %19 ]
%34 = getelementptr inbounds i8, i8* %33, i64 -1
%35 = icmp ugt i8* %34, %0
br i1 %35, label %13, label %36
36: ; preds = %32, %9
ret void
}