#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 *memcpy(void *, void const *, size_t);
void *memmove(void *dst, const void *src, size_t len) {
  if ((size_t)dst - (size_t)src >= len) {
    return memcpy(dst, src, len);
  } else {
    const char *end = dst;
    const char *s = (const char *)src + len;
    char *d = (char *)dst + len;
    while (d != end)
      *--d = *--s;
  }
  return dst;
}


x86 assembly (clang, -O0):
<memmove>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%rcx
sub    %rcx,%rax
cmp    -0x20(%rbp),%rax
jb     115b <memmove+0x4b>
mov    -0x10(%rbp),%rdi
mov    %rdi,-0x40(%rbp)
mov    -0x18(%rbp),%rsi
mov    -0x20(%rbp),%rdx
call   1030 <memcpy@plt>
mov    -0x40(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    11bf <memmove+0xaf>
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x18(%rbp),%rax
add    -0x20(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x10(%rbp),%rax
add    -0x20(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0x38(%rbp),%rax
cmp    -0x28(%rbp),%rax
je     11b2 <memmove+0xa2>
mov    -0x30(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x30(%rbp)
mov    -0x1(%rax),%cl
mov    -0x38(%rbp),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,-0x38(%rbp)
mov    %cl,-0x1(%rax)
jmp    117b <memmove+0x6b>
jmp    11b7 <memmove+0xa7>
mov    -0x10(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<memmove>:
push   %r14
push   %rbx
push   %rax
mov    %rdi,%r14
mov    %rdi,%rax
sub    %rsi,%rax
cmp    %rdx,%rax
jae    11c6 <memmove+0xb6>
lea    (%r14,%rdx,1),%r8
lea    (%rsi,%rdx,1),%r10
cmp    $0x4,%rdx
jb     1146 <memmove+0x36>
cmp    %r14,%r10
jbe    11d9 <memmove+0xc9>
cmp    %rsi,%r8
jbe    11d9 <memmove+0xc9>
mov    %r8,%rsi
mov    %r10,%rax
mov    %esi,%edx
sub    %r14d,%edx
mov    %r14,%rcx
not    %rcx
add    %rsi,%rcx
and    $0x7,%rdx
je     1175 <memmove+0x65>
movzbl -0x1(%rax),%ebx
add    $0xffffffffffffffff,%rax
mov    %bl,-0x1(%rsi)
add    $0xffffffffffffffff,%rsi
add    $0xffffffffffffffff,%rdx
jne    1160 <memmove+0x50>
cmp    $0x7,%rcx
jb     11ce <memmove+0xbe>
add    $0xffffffffffffffff,%rax
nop
movzbl (%rax),%ecx
mov    %cl,-0x1(%rsi)
movzbl -0x1(%rax),%ecx
mov    %cl,-0x2(%rsi)
movzbl -0x2(%rax),%ecx
mov    %cl,-0x3(%rsi)
movzbl -0x3(%rax),%ecx
mov    %cl,-0x4(%rsi)
movzbl -0x4(%rax),%ecx
mov    %cl,-0x5(%rsi)
movzbl -0x5(%rax),%ecx
mov    %cl,-0x6(%rsi)
movzbl -0x6(%rax),%ecx
mov    %cl,-0x7(%rsi)
movzbl -0x7(%rax),%ecx
mov    %cl,-0x8(%rsi)
add    $0xfffffffffffffff8,%rsi
add    $0xfffffffffffffff8,%rax
cmp    %r14,%rsi
jne    1180 <memmove+0x70>
jmp    11ce <memmove+0xbe>
mov    %r14,%rdi
call   1030 <memcpy@plt>
mov    %r14,%rax
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret
cmp    $0x10,%rdx
jae    11e6 <memmove+0xd6>
xor    %edi,%edi
jmp    12a2 <memmove+0x192>
mov    %rdx,%rdi
and    $0xfffffffffffffff0,%rdi
lea    -0x10(%rdi),%rcx
mov    %rcx,%rax
shr    $0x4,%rax
add    $0x1,%rax
mov    %eax,%r9d
and    $0x3,%r9d
cmp    $0x30,%rcx
jae    120d <memmove+0xfd>
xor    %ecx,%ecx
jmp    1257 <memmove+0x147>
and    $0xfffffffffffffffc,%rax
lea    -0x10(%r10),%r11
lea    -0x10(%r8),%rbx
xor    %ecx,%ecx
nopl   0x0(%rax,%rax,1)
movups (%r11,%rcx,1),%xmm0
movups %xmm0,(%rbx,%rcx,1)
movups -0x10(%r11,%rcx,1),%xmm0
movups %xmm0,-0x10(%rbx,%rcx,1)
movups -0x20(%r11,%rcx,1),%xmm0
movups %xmm0,-0x20(%rbx,%rcx,1)
movups -0x30(%r11,%rcx,1),%xmm0
movups %xmm0,-0x30(%rbx,%rcx,1)
add    $0xffffffffffffffc0,%rcx
add    $0xfffffffffffffffc,%rax
jne    1220 <memmove+0x110>
neg    %rcx
test   %r9,%r9
je     1294 <memmove+0x184>
mov    %rdx,%rbx
sub    %rcx,%rbx
lea    (%rsi,%rbx,1),%rax
add    $0xfffffffffffffff0,%rax
lea    (%r14,%rbx,1),%rcx
add    $0xfffffffffffffff0,%rcx
shl    $0x4,%r9
xor    %esi,%esi
nopl   0x0(%rax,%rax,1)
movups (%rax,%rsi,1),%xmm0
movups %xmm0,(%rcx,%rsi,1)
add    $0xfffffffffffffff0,%rsi
mov    %r9,%rbx
add    %rsi,%rbx
jne    1280 <memmove+0x170>
cmp    %rdx,%rdi
je     11ce <memmove+0xbe>
test   $0xc,%dl
je     12e1 <memmove+0x1d1>
mov    %rdx,%r9
and    $0xfffffffffffffffc,%r9
mov    %r9,%rcx
neg    %rcx
mov    %r8,%rsi
sub    %r9,%rsi
mov    %r10,%rax
sub    %r9,%rax
neg    %rdi
xchg   %ax,%ax
mov    -0x4(%r10,%rdi,1),%ebx
mov    %ebx,-0x4(%r8,%rdi,1)
add    $0xfffffffffffffffc,%rdi
cmp    %rdi,%rcx
jne    12c0 <memmove+0x1b0>
cmp    %rdx,%r9
jne    114c <memmove+0x3c>
jmp    11ce <memmove+0xbe>
sub    %rdi,%r10
sub    %rdi,%r8
jmp    1146 <memmove+0x36>

LLVM IR (-O0):
define i8* @memmove(i8* %0, i8* %1, i64 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca i64
%8 = alloca i8*
%9 = alloca i8*
%10 = alloca i8*
store i8* %0, i8** %5
store i8* %1, i8** %6
store i64 %2, i64* %7
%11 = load i8*, i8** %5
%12 = ptrtoint i8* %11 to i64
%13 = load i8*, i8** %6
%14 = ptrtoint i8* %13 to i64
%15 = sub i64 %12, %14
%16 = load i64, i64* %7
%17 = icmp uge i64 %15, %16
br i1 %17, label %18, label %22
18: ; preds = %3
%19 = load i8*, i8** %5
%20 = load i8*, i8** %6
%21 = load i64, i64* %7
store i8* %19, i8** %4
br label %43
22: ; preds = %3
%23 = load i8*, i8** %5
store i8* %23, i8** %8
%24 = load i8*, i8** %6
%25 = load i64, i64* %7
%26 = getelementptr inbounds i8, i8* %24, i64 %25
store i8* %26, i8** %9
%27 = load i8*, i8** %5
%28 = load i64, i64* %7
%29 = getelementptr inbounds i8, i8* %27, i64 %28
store i8* %29, i8** %10
br label %30
30: ; preds = %34, %22
%31 = load i8*, i8** %10
%32 = load i8*, i8** %8
%33 = icmp ne i8* %31, %32
br i1 %33, label %34, label %40
34: ; preds = %30
%35 = load i8*, i8** %9
%36 = getelementptr inbounds i8, i8* %35, i32 -1
store i8* %36, i8** %9
%37 = load i8, i8* %36
%38 = load i8*, i8** %10
%39 = getelementptr inbounds i8, i8* %38, i32 -1
store i8* %39, i8** %10
store i8 %37, i8* %39
br label %30
40: ; preds = %30
br label %41
41: ; preds = %40
%42 = load i8*, i8** %5
store i8* %42, i8** %4
br label %43
43: ; preds = %41, %18
%44 = load i8*, i8** %4
ret i8* %44
}

LLVM IR (-O2):
define i8* @memmove(i8* returned %0, i8* %1, i64 %2) {
%4 = ptrtoint i8* %0 to i64
%5 = ptrtoint i8* %1 to i64
%6 = sub i64 %4, %5
%7 = icmp ult i64 %6, %2
br i1 %7, label %9, label %8
8: ; preds = %3
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 %1, i64 %2, i1 false)
br label %182
9: ; preds = %3
%10 = getelementptr i8, i8* %0, i64 %2
%11 = getelementptr i8, i8* %1, i64 %2
%12 = icmp ult i64 %2, 4
br i1 %12, label %132, label %13
13: ; preds = %9
%14 = icmp ugt i8* %11, %0
%15 = icmp ugt i8* %10, %1
%16 = and i1 %14, %15
br i1 %16, label %132, label %17
17: ; preds = %13
%18 = icmp ult i64 %2, 16
br i1 %18, label %108, label %19
19: ; preds = %17
%20 = and i64 %2, -16
%21 = add i64 %20, -16
%22 = lshr exact i64 %21, 4
%23 = add nuw nsw i64 %22, 1
%24 = and i64 %23, 3
%25 = icmp ult i64 %21, 48
br i1 %25, label %78, label %26
26: ; preds = %19
%27 = and i64 %23, 2305843009213693948
%28 = getelementptr i8, i8* %10, i64 -1
%29 = getelementptr i8, i8* %11, i64 -1
%30 = getelementptr inbounds i8, i8* %29, i64 -15
%31 = getelementptr inbounds i8, i8* %28, i64 -15
%32 = getelementptr i8, i8* %10, i64 -1
%33 = getelementptr i8, i8* %11, i64 -1
%34 = getelementptr inbounds i8, i8* %33, i64 -15
%35 = getelementptr inbounds i8, i8* %32, i64 -15
%36 = getelementptr i8, i8* %10, i64 -1
%37 = getelementptr i8, i8* %11, i64 -1
%38 = getelementptr inbounds i8, i8* %37, i64 -15
%39 = getelementptr inbounds i8, i8* %36, i64 -15
%40 = getelementptr i8, i8* %10, i64 -1
%41 = getelementptr i8, i8* %11, i64 -1
%42 = getelementptr inbounds i8, i8* %41, i64 -15
%43 = getelementptr inbounds i8, i8* %40, i64 -15
br label %44
44: ; preds = %44, %26
%45 = phi i64 [ 0, %26 ], [ %75, %44 ]
%46 = phi i64 [ 0, %26 ], [ %76, %44 ]
%47 = sub i64 0, %45
%48 = sub i64 0, %45
%49 = getelementptr inbounds i8, i8* %30, i64 %48
%50 = bitcast i8* %49 to <16 x i8>*
%51 = load <16 x i8>, <16 x i8>* %50
%52 = getelementptr inbounds i8, i8* %31, i64 %47
%53 = bitcast i8* %52 to <16 x i8>*
store <16 x i8> %51, <16 x i8>* %53
%54 = sub nuw nsw i64 -16, %45
%55 = sub nuw nsw i64 -16, %45
%56 = getelementptr inbounds i8, i8* %34, i64 %55
%57 = bitcast i8* %56 to <16 x i8>*
%58 = load <16 x i8>, <16 x i8>* %57
%59 = getelementptr inbounds i8, i8* %35, i64 %54
%60 = bitcast i8* %59 to <16 x i8>*
store <16 x i8> %58, <16 x i8>* %60
%61 = sub nuw nsw i64 -32, %45
%62 = sub nuw nsw i64 -32, %45
%63 = getelementptr inbounds i8, i8* %38, i64 %62
%64 = bitcast i8* %63 to <16 x i8>*
%65 = load <16 x i8>, <16 x i8>* %64
%66 = getelementptr inbounds i8, i8* %39, i64 %61
%67 = bitcast i8* %66 to <16 x i8>*
store <16 x i8> %65, <16 x i8>* %67
%68 = sub nuw nsw i64 -48, %45
%69 = sub nuw nsw i64 -48, %45
%70 = getelementptr inbounds i8, i8* %42, i64 %69
%71 = bitcast i8* %70 to <16 x i8>*
%72 = load <16 x i8>, <16 x i8>* %71
%73 = getelementptr inbounds i8, i8* %43, i64 %68
%74 = bitcast i8* %73 to <16 x i8>*
store <16 x i8> %72, <16 x i8>* %74
%75 = add nuw i64 %45, 64
%76 = add i64 %46, 4
%77 = icmp eq i64 %76, %27
br i1 %77, label %78, label %44
78: ; preds = %44, %19
%79 = phi i64 [ 0, %19 ], [ %75, %44 ]
%80 = icmp eq i64 %24, 0
br i1 %80, label %99, label %81
81: ; preds = %78
%82 = getelementptr i8, i8* %10, i64 -1
%83 = getelementptr i8, i8* %11, i64 -1
%84 = getelementptr inbounds i8, i8* %83, i64 -15
%85 = getelementptr inbounds i8, i8* %82, i64 -15
br label %86
86: ; preds = %86, %81
%87 = phi i64 [ %79, %81 ], [ %96, %86 ]
%88 = phi i64 [ 0, %81 ], [ %97, %86 ]
%89 = sub i64 0, %87
%90 = sub i64 0, %87
%91 = getelementptr inbounds i8, i8* %84, i64 %90
%92 = bitcast i8* %91 to <16 x i8>*
%93 = load <16 x i8>, <16 x i8>* %92
%94 = getelementptr inbounds i8, i8* %85, i64 %89
%95 = bitcast i8* %94 to <16 x i8>*
store <16 x i8> %93, <16 x i8>* %95
%96 = add nuw i64 %87, 16
%97 = add i64 %88, 1
%98 = icmp eq i64 %97, %24
br i1 %98, label %99, label %86
99: ; preds = %86, %78
%100 = icmp eq i64 %20, %2
br i1 %100, label %182, label %101
101: ; preds = %99
%102 = sub i64 0, %20
%103 = getelementptr i8, i8* %11, i64 %102
%104 = sub i64 0, %20
%105 = getelementptr i8, i8* %10, i64 %104
%106 = and i64 %2, 12
%107 = icmp eq i64 %106, 0
br i1 %107, label %132, label %108
108: ; preds = %17, %101
%109 = phi i64 [ %20, %101 ], [ 0, %17 ]
%110 = and i64 %2, -4
%111 = sub i64 0, %110
%112 = getelementptr i8, i8* %10, i64 %111
%113 = sub i64 0, %110
%114 = getelementptr i8, i8* %11, i64 %113
%115 = getelementptr i8, i8* %10, i64 -1
%116 = getelementptr i8, i8* %11, i64 -1
%117 = getelementptr inbounds i8, i8* %116, i64 -3
%118 = getelementptr inbounds i8, i8* %115, i64 -3
br label %119
119: ; preds = %119, %108
%120 = phi i64 [ %109, %108 ], [ %128, %119 ]
%121 = sub i64 0, %120
%122 = sub i64 0, %120
%123 = getelementptr inbounds i8, i8* %117, i64 %122
%124 = bitcast i8* %123 to <4 x i8>*
%125 = load <4 x i8>, <4 x i8>* %124
%126 = getelementptr inbounds i8, i8* %118, i64 %121
%127 = bitcast i8* %126 to <4 x i8>*
store <4 x i8> %125, <4 x i8>* %127
%128 = add nuw i64 %120, 4
%129 = icmp eq i64 %128, %110
br i1 %129, label %130, label %119
130: ; preds = %119
%131 = icmp eq i64 %110, %2
br i1 %131, label %182, label %132
132: ; preds = %13, %9, %101, %130
%133 = phi i8* [ %10, %9 ], [ %10, %13 ], [ %105, %101 ], [ %112, %130 ]
%134 = phi i8* [ %11, %9 ], [ %11, %13 ], [ %103, %101 ], [ %114, %130 ]
%135 = ptrtoint i8* %133 to i64
%136 = sub i64 %135, %4
%137 = xor i64 %4, -1
%138 = add i64 %137, %135
%139 = and i64 %136, 7
%140 = icmp eq i64 %139, 0
br i1 %140, label %150, label %141
141: ; preds = %132, %141
%142 = phi i8* [ %147, %141 ], [ %133, %132 ]
%143 = phi i8* [ %145, %141 ], [ %134, %132 ]
%144 = phi i64 [ %148, %141 ], [ 0, %132 ]
%145 = getelementptr inbounds i8, i8* %143, i64 -1
%146 = load i8, i8* %145
%147 = getelementptr inbounds i8, i8* %142, i64 -1
store i8 %146, i8* %147
%148 = add i64 %144, 1
%149 = icmp eq i64 %148, %139
br i1 %149, label %150, label %141
150: ; preds = %141, %132
%151 = phi i8* [ %133, %132 ], [ %147, %141 ]
%152 = phi i8* [ %134, %132 ], [ %145, %141 ]
%153 = icmp ult i64 %138, 7
br i1 %153, label %182, label %154
154: ; preds = %150, %154
%155 = phi i8* [ %180, %154 ], [ %151, %150 ]
%156 = phi i8* [ %178, %154 ], [ %152, %150 ]
%157 = getelementptr inbounds i8, i8* %156, i64 -1
%158 = load i8, i8* %157
%159 = getelementptr inbounds i8, i8* %155, i64 -1
store i8 %158, i8* %159
%160 = getelementptr inbounds i8, i8* %156, i64 -2
%161 = load i8, i8* %160
%162 = getelementptr inbounds i8, i8* %155, i64 -2
store i8 %161, i8* %162
%163 = getelementptr inbounds i8, i8* %156, i64 -3
%164 = load i8, i8* %163
%165 = getelementptr inbounds i8, i8* %155, i64 -3
store i8 %164, i8* %165
%166 = getelementptr inbounds i8, i8* %156, i64 -4
%167 = load i8, i8* %166
%168 = getelementptr inbounds i8, i8* %155, i64 -4
store i8 %167, i8* %168
%169 = getelementptr inbounds i8, i8* %156, i64 -5
%170 = load i8, i8* %169
%171 = getelementptr inbounds i8, i8* %155, i64 -5
store i8 %170, i8* %171
%172 = getelementptr inbounds i8, i8* %156, i64 -6
%173 = load i8, i8* %172
%174 = getelementptr inbounds i8, i8* %155, i64 -6
store i8 %173, i8* %174
%175 = getelementptr inbounds i8, i8* %156, i64 -7
%176 = load i8, i8* %175
%177 = getelementptr inbounds i8, i8* %155, i64 -7
store i8 %176, i8* %177
%178 = getelementptr inbounds i8, i8* %156, i64 -8
%179 = load i8, i8* %178
%180 = getelementptr inbounds i8, i8* %155, i64 -8
store i8 %179, i8* %180
%181 = icmp eq i8* %180, %0
br i1 %181, label %182, label %154
182: ; preds = %150, %154, %99, %130, %8
ret i8* %0
}