#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 *, unsigned long);
void *memmove(void *dst, const void *src, unsigned long n) {
  if (dst < src)
    return memcpy(dst, src, n);
  else if (dst == src)
    return dst;
  void *r = dst;
  char *d = dst + n - 1;
  const char *s = src + n - 1;
  while (n--)
    *(d--) = *(s--);
  return r;
}


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
cmp    -0x18(%rbp),%rax
jae    1154 <memmove+0x44>
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    11e4 <memmove+0xd4>
mov    -0x10(%rbp),%rax
cmp    -0x18(%rbp),%rax
jne    116f <memmove+0x5f>
mov    -0x10(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    11e4 <memmove+0xd4>
jmp    1174 <memmove+0x64>
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rax
add    -0x20(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x30(%rbp)
mov    -0x18(%rbp),%rax
add    -0x20(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x38(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x20(%rbp)
cmp    $0x0,%rax
je     11dc <memmove+0xcc>
mov    -0x38(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x38(%rbp)
mov    (%rax),%cl
mov    -0x30(%rbp),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,-0x30(%rbp)
mov    %cl,(%rax)
jmp    119c <memmove+0x8c>
mov    -0x28(%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
cmp    %rsi,%rdi
jae    112f <memmove+0x1f>
mov    %r14,%rdi
call   1030 <memcpy@plt>
mov    %r14,%rax
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret
je     1124 <memmove+0x14>
test   %rdx,%rdx
je     1124 <memmove+0x14>
lea    (%rsi,%rdx,1),%r9
lea    (%r14,%rdx,1),%r8
cmp    $0x4,%rdx
jb     1156 <memmove+0x46>
cmp    %r14,%r9
jbe    11f6 <memmove+0xe6>
cmp    %rsi,%r8
jbe    11f6 <memmove+0xe6>
mov    %r9,%rsi
mov    %r8,%rax
mov    %rdx,%rcx
lea    -0x1(%rcx),%r8
mov    %rcx,%rdi
and    $0x7,%rdi
je     118b <memmove+0x7b>
xor    %edx,%edx
xchg   %ax,%ax
movzbl -0x1(%rsi),%ebx
add    $0xffffffffffffffff,%rsi
mov    %bl,-0x1(%rax)
add    $0xffffffffffffffff,%rax
add    $0x1,%rdx
cmp    %rdx,%rdi
jne    1170 <memmove+0x60>
sub    %rdx,%rcx
cmp    $0x7,%r8
jb     1124 <memmove+0x14>
neg    %rcx
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
movzbl -0x1(%rsi,%rdx,1),%ebx
mov    %bl,-0x1(%rax,%rdx,1)
movzbl -0x2(%rsi,%rdx,1),%ebx
mov    %bl,-0x2(%rax,%rdx,1)
movzbl -0x3(%rsi,%rdx,1),%ebx
mov    %bl,-0x3(%rax,%rdx,1)
movzbl -0x4(%rsi,%rdx,1),%ebx
mov    %bl,-0x4(%rax,%rdx,1)
movzbl -0x5(%rsi,%rdx,1),%ebx
mov    %bl,-0x5(%rax,%rdx,1)
movzbl -0x6(%rsi,%rdx,1),%ebx
mov    %bl,-0x6(%rax,%rdx,1)
movzbl -0x7(%rsi,%rdx,1),%ebx
mov    %bl,-0x7(%rax,%rdx,1)
movzbl -0x8(%rsi,%rdx,1),%ebx
mov    %bl,-0x8(%rax,%rdx,1)
add    $0xfffffffffffffff8,%rdx
cmp    %rdx,%rcx
jne    11a0 <memmove+0x90>
jmp    1124 <memmove+0x14>
cmp    $0x10,%rdx
jae    1203 <memmove+0xf3>
xor    %edi,%edi
jmp    12c2 <memmove+0x1b2>
mov    %rdx,%rdi
and    $0xfffffffffffffff0,%rdi
lea    -0x10(%rdi),%rax
mov    %rax,%rcx
shr    $0x4,%rcx
add    $0x1,%rcx
mov    %ecx,%r10d
and    $0x3,%r10d
cmp    $0x30,%rax
jae    122a <memmove+0x11a>
xor    %eax,%eax
jmp    1277 <memmove+0x167>
and    $0xfffffffffffffffc,%rcx
lea    -0x10(%r8),%r11
lea    -0x10(%r9),%rbx
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
movups (%rbx,%rax,1),%xmm0
movups %xmm0,(%r11,%rax,1)
movups -0x10(%rbx,%rax,1),%xmm0
movups %xmm0,-0x10(%r11,%rax,1)
movups -0x20(%rbx,%rax,1),%xmm0
movups %xmm0,-0x20(%r11,%rax,1)
movups -0x30(%rbx,%rax,1),%xmm0
movups %xmm0,-0x30(%r11,%rax,1)
add    $0xffffffffffffffc0,%rax
add    $0xfffffffffffffffc,%rcx
jne    1240 <memmove+0x130>
neg    %rax
test   %r10,%r10
je     12b4 <memmove+0x1a4>
mov    %rdx,%rcx
sub    %rax,%rcx
lea    (%r14,%rcx,1),%rax
add    $0xfffffffffffffff0,%rax
add    %rsi,%rcx
add    $0xfffffffffffffff0,%rcx
shl    $0x4,%r10
xor    %esi,%esi
nopw   0x0(%rax,%rax,1)
movups (%rcx,%rsi,1),%xmm0
movups %xmm0,(%rax,%rsi,1)
add    $0xfffffffffffffff0,%rsi
mov    %r10,%rbx
add    %rsi,%rbx
jne    12a0 <memmove+0x190>
cmp    %rdx,%rdi
je     1124 <memmove+0x14>
test   $0xc,%dl
je     1311 <memmove+0x201>
mov    %rdx,%r10
and    $0xfffffffffffffffc,%r10
mov    %r10,%r11
neg    %r11
mov    %r9,%rsi
sub    %r10,%rsi
mov    %r8,%rax
sub    %r10,%rax
mov    %edx,%ecx
and    $0x3,%ecx
neg    %rdi
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
mov    -0x4(%r9,%rdi,1),%ebx
mov    %ebx,-0x4(%r8,%rdi,1)
add    $0xfffffffffffffffc,%rdi
cmp    %rdi,%r11
jne    12f0 <memmove+0x1e0>
cmp    %rdx,%r10
je     1124 <memmove+0x14>
jmp    115f <memmove+0x4f>
and    $0xf,%edx
sub    %rdi,%r8
sub    %rdi,%r9
jmp    1156 <memmove+0x46>

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 = load i8*, i8** %6
%13 = icmp ult i8* %11, %12
br i1 %13, label %14, label %18
14: ; preds = %3
%15 = load i8*, i8** %5
%16 = load i8*, i8** %6
%17 = load i64, i64* %7
store i8* %15, i8** %4
br label %47
18: ; preds = %3
%19 = load i8*, i8** %5
%20 = load i8*, i8** %6
%21 = icmp eq i8* %19, %20
br i1 %21, label %22, label %24
22: ; preds = %18
%23 = load i8*, i8** %5
store i8* %23, i8** %4
br label %47
24: ; preds = %18
br label %25
25: ; preds = %24
%26 = load i8*, i8** %5
store i8* %26, i8** %8
%27 = load i8*, i8** %5
%28 = load i64, i64* %7
%29 = getelementptr i8, i8* %27, i64 %28
%30 = getelementptr i8, i8* %29, i64 -1
store i8* %30, i8** %9
%31 = load i8*, i8** %6
%32 = load i64, i64* %7
%33 = getelementptr i8, i8* %31, i64 %32
%34 = getelementptr i8, i8* %33, i64 -1
store i8* %34, i8** %10
br label %35
35: ; preds = %39, %25
%36 = load i64, i64* %7
%37 = add i64 %36, -1
store i64 %37, i64* %7
%38 = icmp ne i64 %36, 0
br i1 %38, label %39, label %45
39: ; preds = %35
%40 = load i8*, i8** %10
%41 = getelementptr inbounds i8, i8* %40, i32 -1
store i8* %41, i8** %10
%42 = load i8, i8* %40
%43 = load i8*, i8** %9
%44 = getelementptr inbounds i8, i8* %43, i32 -1
store i8* %44, i8** %9
store i8 %42, i8* %43
br label %35
45: ; preds = %35
%46 = load i8*, i8** %8
store i8* %46, i8** %4
br label %47
47: ; preds = %45, %22, %14
%48 = load i8*, i8** %4
ret i8* %48
}

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