#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 */
void reverse_bytes(void const *restrict in, size_t size, void *restrict out) {
  unsigned char const *const p_in = (unsigned char const *restrict)in;
  unsigned char *const p_out = (unsigned char *restrict)out;
  for (size_t i = 0, j = (size - 1); i < size; i++, j--)
    p_out[j] = p_in[i];
}


x86 assembly (clang, -O0):
<reverse_bytes>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x28(%rbp)
movq   $0x0,-0x30(%rbp)
mov    -0x10(%rbp),%rax
sub    $0x1,%rax
mov    %rax,-0x38(%rbp)
mov    -0x30(%rbp),%rax
cmp    -0x10(%rbp),%rax
jae    1175 <reverse_bytes+0x75>
mov    -0x20(%rbp),%rax
mov    -0x30(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x28(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x30(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x30(%rbp)
mov    -0x38(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x38(%rbp)
jmp    1134 <reverse_bytes+0x34>
pop    %rbp
ret

x86 assembly (clang, -O2):
<reverse_bytes>:
test   %rsi,%rsi
je     1254 <reverse_bytes+0x154>
cmp    $0x8,%rsi
jae    111a <reverse_bytes+0x1a>
xor    %r9d,%r9d
mov    %rsi,%r8
jmp    122b <reverse_bytes+0x12b>
cmp    $0x20,%rsi
jae    1128 <reverse_bytes+0x28>
xor    %r9d,%r9d
jmp    11ce <reverse_bytes+0xce>
mov    %rsi,%r9
and    $0xffffffffffffffe0,%r9
lea    (%rsi,%rdx,1),%r8
add    $0xfffffffffffffff0,%r8
xor    %eax,%eax
pxor   %xmm0,%xmm0
nopl   (%rax)
movdqu (%rdi,%rax,1),%xmm1
movdqu 0x10(%rdi,%rax,1),%xmm2
movdqa %xmm1,%xmm3
punpcklbw %xmm0,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
punpckhbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm3,%xmm1
movdqu %xmm1,(%r8)
movdqa %xmm2,%xmm1
punpcklbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
punpckhbw %xmm0,%xmm2
pshufd $0x4e,%xmm2,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
pshufhw $0x1b,%xmm2,%xmm2
packuswb %xmm1,%xmm2
movdqu %xmm2,-0x10(%r8)
add    $0x20,%rax
add    $0xffffffffffffffe0,%r8
cmp    %rax,%r9
jne    1140 <reverse_bytes+0x40>
cmp    %rsi,%r9
je     1254 <reverse_bytes+0x154>
test   $0x18,%sil
je     1224 <reverse_bytes+0x124>
mov    %r9,%rax
mov    %rsi,%r9
and    $0xfffffffffffffff8,%r9
mov    %esi,%r8d
and    $0x7,%r8d
mov    %rsi,%rcx
sub    %rax,%rcx
add    %rdx,%rcx
add    $0xfffffffffffffff8,%rcx
pxor   %xmm0,%xmm0
movq   (%rdi,%rax,1),%xmm1
punpcklbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm1,%xmm1
movq   %xmm1,(%rcx)
add    $0x8,%rax
add    $0xfffffffffffffff8,%rcx
cmp    %rax,%r9
jne    11f0 <reverse_bytes+0xf0>
cmp    %rsi,%r9
jne    122b <reverse_bytes+0x12b>
jmp    1254 <reverse_bytes+0x154>
mov    %esi,%r8d
and    $0x1f,%r8d
lea    (%r8,%rdx,1),%rax
add    $0xffffffffffffffff,%rax
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzbl (%rdi,%r9,1),%ecx
mov    %cl,(%rax)
add    $0x1,%r9
add    $0xffffffffffffffff,%rax
cmp    %r9,%rsi
jne    1240 <reverse_bytes+0x140>
ret

LLVM IR (-O0):
define void @reverse_bytes(i8* noalias %0, i64 %1, i8* noalias %2) {
%4 = alloca i8*
%5 = alloca i64
%6 = alloca i8*
%7 = alloca i8*
%8 = alloca i8*
%9 = alloca i64
%10 = alloca i64
store i8* %0, i8** %4
store i64 %1, i64* %5
store i8* %2, i8** %6
%11 = load i8*, i8** %4
store i8* %11, i8** %7
%12 = load i8*, i8** %6
store i8* %12, i8** %8
store i64 0, i64* %9
%13 = load i64, i64* %5
%14 = sub i64 %13, 1
store i64 %14, i64* %10
br label %15
15: ; preds = %27, %3
%16 = load i64, i64* %9
%17 = load i64, i64* %5
%18 = icmp ult i64 %16, %17
br i1 %18, label %19, label %32
19: ; preds = %15
%20 = load i8*, i8** %7
%21 = load i64, i64* %9
%22 = getelementptr inbounds i8, i8* %20, i64 %21
%23 = load i8, i8* %22
%24 = load i8*, i8** %8
%25 = load i64, i64* %10
%26 = getelementptr inbounds i8, i8* %24, i64 %25
store i8 %23, i8* %26
br label %27
27: ; preds = %19
%28 = load i64, i64* %9
%29 = add i64 %28, 1
store i64 %29, i64* %9
%30 = load i64, i64* %10
%31 = add i64 %30, -1
store i64 %31, i64* %10
br label %15
32: ; preds = %15
ret void
}

LLVM IR (-O2):
define void @reverse_bytes(i8* noalias nocapture %0, i64 %1, i8* noalias nocapture writeonly %2) {
%4 = icmp eq i64 %1, 0
br i1 %4, label %59, label %5
5: ; preds = %3
%6 = icmp ult i64 %1, 8
br i1 %6, label %56, label %7
7: ; preds = %5
%8 = icmp ult i64 %1, 32
br i1 %8, label %37, label %9
9: ; preds = %7
%10 = and i64 %1, -32
br label %11
11: ; preds = %11, %9
%12 = phi i64 [ 0, %9 ], [ %29, %11 ]
%13 = xor i64 %12, -1
%14 = add i64 %13, %1
%15 = getelementptr inbounds i8, i8* %0, i64 %12
%16 = bitcast i8* %15 to <16 x i8>*
%17 = load <16 x i8>, <16 x i8>* %16
%18 = getelementptr inbounds i8, i8* %15, i64 16
%19 = bitcast i8* %18 to <16 x i8>*
%20 = load <16 x i8>, <16 x i8>* %19
%21 = getelementptr inbounds i8, i8* %2, i64 %14
%22 = shufflevector <16 x i8> %17, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%23 = getelementptr inbounds i8, i8* %21, i64 -15
%24 = bitcast i8* %23 to <16 x i8>*
store <16 x i8> %22, <16 x i8>* %24
%25 = shufflevector <16 x i8> %20, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%26 = getelementptr inbounds i8, i8* %21, i64 -16
%27 = getelementptr inbounds i8, i8* %26, i64 -15
%28 = bitcast i8* %27 to <16 x i8>*
store <16 x i8> %25, <16 x i8>* %28
%29 = add nuw i64 %12, 32
%30 = icmp eq i64 %29, %10
br i1 %30, label %31, label %11
31: ; preds = %11
%32 = icmp eq i64 %10, %1
br i1 %32, label %59, label %33
33: ; preds = %31
%34 = and i64 %1, 31
%35 = and i64 %1, 24
%36 = icmp eq i64 %35, 0
br i1 %36, label %56, label %37
37: ; preds = %7, %33
%38 = phi i64 [ %10, %33 ], [ 0, %7 ]
%39 = and i64 %1, -8
%40 = and i64 %1, 7
%41 = getelementptr inbounds i8, i8* %2, i64 -7
br label %42
42: ; preds = %42, %37
%43 = phi i64 [ %38, %37 ], [ %52, %42 ]
%44 = xor i64 %43, -1
%45 = add i64 %44, %1
%46 = getelementptr inbounds i8, i8* %0, i64 %43
%47 = bitcast i8* %46 to <8 x i8>*
%48 = load <8 x i8>, <8 x i8>* %47
%49 = shufflevector <8 x i8> %48, <8 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%50 = getelementptr inbounds i8, i8* %41, i64 %45
%51 = bitcast i8* %50 to <8 x i8>*
store <8 x i8> %49, <8 x i8>* %51
%52 = add nuw i64 %43, 8
%53 = icmp eq i64 %52, %39
br i1 %53, label %54, label %42
54: ; preds = %42
%55 = icmp eq i64 %39, %1
br i1 %55, label %59, label %56
56: ; preds = %5, %33, %54
%57 = phi i64 [ %1, %5 ], [ %34, %33 ], [ %40, %54 ]
%58 = phi i64 [ 0, %5 ], [ %10, %33 ], [ %39, %54 ]
br label %60
59: ; preds = %60, %31, %54, %3
ret void
60: ; preds = %56, %60
%61 = phi i64 [ %63, %60 ], [ %57, %56 ]
%62 = phi i64 [ %67, %60 ], [ %58, %56 ]
%63 = add i64 %61, -1
%64 = getelementptr inbounds i8, i8* %0, i64 %62
%65 = load i8, i8* %64
%66 = getelementptr inbounds i8, i8* %2, i64 %63
store i8 %65, i8* %66
%67 = add nuw i64 %62, 1
%68 = icmp eq i64 %67, %1
br i1 %68, label %59, label %60
}