void copy(void) {
  unsigned long *b = (void *)0x2100;
  unsigned long **ptr = (void *)b++;
  unsigned long *a = *ptr;
  unsigned long i = *b++;
  while (i--) {
    *b++ = *a++;
  }
  *ptr = a;
}


x86 assembly (clang, -O0):
<copy>:
push   %rbp
mov    %rsp,%rbp
mov    $0x2100,%eax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x8(%rbp)
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x20(%rbp)
cmp    $0x0,%rax
je     1183 <copy+0x83>
mov    -0x18(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x18(%rbp)
mov    (%rax),%rcx
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x8,%rdx
mov    %rdx,-0x8(%rbp)
mov    %rcx,(%rax)
jmp    1141 <copy+0x41>
mov    -0x18(%rbp),%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<copy>:
mov    0x2100,%rax
mov    0x2108,%rcx
test   %rcx,%rcx
je     12b3 <copy+0x1b3>
mov    $0x2110,%edx
cmp    $0x4,%rcx
jb     1233 <copy+0x133>
lea    (%rax,%rcx,8),%rsi
cmp    $0x2111,%rsi
jb     1146 <copy+0x46>
lea    0x2110(,%rcx,8),%rsi
cmp    %rsi,%rax
jb     1233 <copy+0x133>
mov    $0x2180,%r10d
mov    %rcx,%r8
and    $0xfffffffffffffffc,%r8
lea    -0x4(%r8),%rdx
mov    %rdx,%rdi
shr    $0x2,%rdi
add    $0x1,%rdi
mov    %edi,%r9d
and    $0x3,%r9d
cmp    $0xc,%rdx
jae    1173 <copy+0x73>
xor    %esi,%esi
jmp    11e0 <copy+0xe0>
and    $0xfffffffffffffffc,%rdi
xor    %esi,%esi
nopl   0x0(%rax)
movups (%rax,%rsi,8),%xmm0
movups 0x10(%rax,%rsi,8),%xmm1
movaps %xmm0,-0x70(%r10,%rsi,8)
movaps %xmm1,-0x60(%r10,%rsi,8)
movups 0x20(%rax,%rsi,8),%xmm0
movups 0x30(%rax,%rsi,8),%xmm1
movaps %xmm0,-0x50(%r10,%rsi,8)
movaps %xmm1,-0x40(%r10,%rsi,8)
movups 0x40(%rax,%rsi,8),%xmm0
movups 0x50(%rax,%rsi,8),%xmm1
movaps %xmm0,-0x30(%r10,%rsi,8)
movaps %xmm1,-0x20(%r10,%rsi,8)
movups 0x60(%rax,%rsi,8),%xmm0
movups 0x70(%rax,%rsi,8),%xmm1
movaps %xmm0,-0x10(%r10,%rsi,8)
movaps %xmm1,(%r10,%rsi,8)
add    $0x10,%rsi
add    $0xfffffffffffffffc,%rdi
jne    1180 <copy+0x80>
test   %r9,%r9
je     121b <copy+0x11b>
lea    (%r10,%rsi,8),%rdi
add    $0xffffffffffffffa0,%rdi
lea    (%rax,%rsi,8),%rsi
add    $0x10,%rsi
shl    $0x5,%r9
xor    %edx,%edx
nopl   0x0(%rax,%rax,1)
movups -0x10(%rsi,%rdx,1),%xmm0
movups (%rsi,%rdx,1),%xmm1
movaps %xmm0,-0x10(%rdi,%rdx,1)
movaps %xmm1,(%rdi,%rdx,1)
add    $0x20,%rdx
cmp    %rdx,%r9
jne    1200 <copy+0x100>
lea    (%rax,%r8,8),%rax
cmp    %r8,%rcx
je     12b3 <copy+0x1b3>
and    $0x3,%ecx
lea    (%r10,%r8,8),%rdx
add    $0xffffffffffffff90,%rdx
lea    -0x1(%rcx),%r8
mov    %rcx,%rdi
and    $0x7,%rdi
je     1258 <copy+0x158>
add    $0xffffffffffffffff,%rcx
mov    (%rax),%rsi
add    $0x8,%rax
mov    %rsi,(%rdx)
add    $0x8,%rdx
add    $0xffffffffffffffff,%rdi
jne    1240 <copy+0x140>
cmp    $0x7,%r8
jb     12b3 <copy+0x1b3>
xor    %esi,%esi
mov    (%rax),%rdi
mov    %rdi,(%rdx,%rsi,8)
mov    0x8(%rax),%rdi
mov    %rdi,0x8(%rdx,%rsi,8)
mov    0x10(%rax),%rdi
mov    %rdi,0x10(%rdx,%rsi,8)
mov    0x18(%rax),%rdi
mov    %rdi,0x18(%rdx,%rsi,8)
mov    0x20(%rax),%rdi
mov    %rdi,0x20(%rdx,%rsi,8)
mov    0x28(%rax),%rdi
mov    %rdi,0x28(%rdx,%rsi,8)
mov    0x30(%rax),%rdi
mov    %rdi,0x30(%rdx,%rsi,8)
mov    0x38(%rax),%rdi
add    $0x40,%rax
mov    %rdi,0x38(%rdx,%rsi,8)
add    $0x8,%rsi
cmp    %rsi,%rcx
jne    1260 <copy+0x160>
mov    %rax,0x2100
ret

LLVM IR (-O0):
define void @copy() {
%1 = alloca i64*
%2 = alloca i64**
%3 = alloca i64*
%4 = alloca i64
store i64* inttoptr (i64 8448 to i64*), i64** %1
%5 = load i64*, i64** %1
%6 = getelementptr inbounds i64, i64* %5, i32 1
store i64* %6, i64** %1
%7 = bitcast i64* %5 to i8*
%8 = bitcast i8* %7 to i64**
store i64** %8, i64*** %2
%9 = load i64**, i64*** %2
%10 = load i64*, i64** %9
store i64* %10, i64** %3
%11 = load i64*, i64** %1
%12 = getelementptr inbounds i64, i64* %11, i32 1
store i64* %12, i64** %1
%13 = load i64, i64* %11
store i64 %13, i64* %4
br label %14
14: ; preds = %18, %0
%15 = load i64, i64* %4
%16 = add i64 %15, -1
store i64 %16, i64* %4
%17 = icmp ne i64 %15, 0
br i1 %17, label %18, label %24
18: ; preds = %14
%19 = load i64*, i64** %3
%20 = getelementptr inbounds i64, i64* %19, i32 1
store i64* %20, i64** %3
%21 = load i64, i64* %19
%22 = load i64*, i64** %1
%23 = getelementptr inbounds i64, i64* %22, i32 1
store i64* %23, i64** %1
store i64 %21, i64* %22
br label %14
24: ; preds = %14
%25 = load i64*, i64** %3
%26 = load i64**, i64*** %2
store i64* %25, i64** %26
ret void
}

LLVM IR (-O2):
define void @copy() {
%1 = load i64*, i64** inttoptr (i64 8448 to i64**)
%2 = load i64, i64* inttoptr (i64 8456 to i64*)
%3 = icmp eq i64 %2, 0
br i1 %3, label %148, label %4
4: ; preds = %0
%5 = icmp ult i64 %2, 4
br i1 %5, label %94, label %6
6: ; preds = %4
%7 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %2
%8 = getelementptr i64, i64* %1, i64 %2
%9 = icmp ugt i64* %8, inttoptr (i64 8464 to i64*)
%10 = icmp ult i64* %1, %7
%11 = and i1 %9, %10
br i1 %11, label %94, label %12
12: ; preds = %6
%13 = and i64 %2, -4
%14 = and i64 %2, 3
%15 = getelementptr i64, i64* %1, i64 %13
%16 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %13
%17 = add i64 %13, -4
%18 = lshr exact i64 %17, 2
%19 = add nuw nsw i64 %18, 1
%20 = and i64 %19, 3
%21 = icmp ult i64 %17, 12
br i1 %21, label %73, label %22
22: ; preds = %12
%23 = and i64 %19, 9223372036854775804
br label %24
24: ; preds = %24, %22
%25 = phi i64 [ 0, %22 ], [ %70, %24 ]
%26 = phi i64 [ 0, %22 ], [ %71, %24 ]
%27 = getelementptr i64, i64* %1, i64 %25
%28 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %25
%29 = bitcast i64* %27 to <2 x i64>*
%30 = load <2 x i64>, <2 x i64>* %29
%31 = getelementptr i64, i64* %27, i64 2
%32 = bitcast i64* %31 to <2 x i64>*
%33 = load <2 x i64>, <2 x i64>* %32
%34 = bitcast i64* %28 to <2 x i64>*
store <2 x i64> %30, <2 x i64>* %34
%35 = getelementptr i64, i64* %28, i64 2
%36 = bitcast i64* %35 to <2 x i64>*
store <2 x i64> %33, <2 x i64>* %36
%37 = or i64 %25, 4
%38 = getelementptr i64, i64* %1, i64 %37
%39 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %37
%40 = bitcast i64* %38 to <2 x i64>*
%41 = load <2 x i64>, <2 x i64>* %40
%42 = getelementptr i64, i64* %38, i64 2
%43 = bitcast i64* %42 to <2 x i64>*
%44 = load <2 x i64>, <2 x i64>* %43
%45 = bitcast i64* %39 to <2 x i64>*
store <2 x i64> %41, <2 x i64>* %45
%46 = getelementptr i64, i64* %39, i64 2
%47 = bitcast i64* %46 to <2 x i64>*
store <2 x i64> %44, <2 x i64>* %47
%48 = or i64 %25, 8
%49 = getelementptr i64, i64* %1, i64 %48
%50 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %48
%51 = bitcast i64* %49 to <2 x i64>*
%52 = load <2 x i64>, <2 x i64>* %51
%53 = getelementptr i64, i64* %49, i64 2
%54 = bitcast i64* %53 to <2 x i64>*
%55 = load <2 x i64>, <2 x i64>* %54
%56 = bitcast i64* %50 to <2 x i64>*
store <2 x i64> %52, <2 x i64>* %56
%57 = getelementptr i64, i64* %50, i64 2
%58 = bitcast i64* %57 to <2 x i64>*
store <2 x i64> %55, <2 x i64>* %58
%59 = or i64 %25, 12
%60 = getelementptr i64, i64* %1, i64 %59
%61 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %59
%62 = bitcast i64* %60 to <2 x i64>*
%63 = load <2 x i64>, <2 x i64>* %62
%64 = getelementptr i64, i64* %60, i64 2
%65 = bitcast i64* %64 to <2 x i64>*
%66 = load <2 x i64>, <2 x i64>* %65
%67 = bitcast i64* %61 to <2 x i64>*
store <2 x i64> %63, <2 x i64>* %67
%68 = getelementptr i64, i64* %61, i64 2
%69 = bitcast i64* %68 to <2 x i64>*
store <2 x i64> %66, <2 x i64>* %69
%70 = add nuw i64 %25, 16
%71 = add nuw i64 %26, 4
%72 = icmp eq i64 %71, %23
br i1 %72, label %73, label %24
73: ; preds = %24, %12
%74 = phi i64 [ 0, %12 ], [ %70, %24 ]
%75 = icmp eq i64 %20, 0
br i1 %75, label %92, label %76
76: ; preds = %73, %76
%77 = phi i64 [ %89, %76 ], [ %74, %73 ]
%78 = phi i64 [ %90, %76 ], [ 0, %73 ]
%79 = getelementptr i64, i64* %1, i64 %77
%80 = getelementptr i64, i64* inttoptr (i64 8464 to i64*), i64 %77
%81 = bitcast i64* %79 to <2 x i64>*
%82 = load <2 x i64>, <2 x i64>* %81
%83 = getelementptr i64, i64* %79, i64 2
%84 = bitcast i64* %83 to <2 x i64>*
%85 = load <2 x i64>, <2 x i64>* %84
%86 = bitcast i64* %80 to <2 x i64>*
store <2 x i64> %82, <2 x i64>* %86
%87 = getelementptr i64, i64* %80, i64 2
%88 = bitcast i64* %87 to <2 x i64>*
store <2 x i64> %85, <2 x i64>* %88
%89 = add nuw i64 %77, 4
%90 = add i64 %78, 1
%91 = icmp eq i64 %90, %20
br i1 %91, label %92, label %76
92: ; preds = %76, %73
%93 = icmp eq i64 %2, %13
br i1 %93, label %148, label %94
94: ; preds = %6, %4, %92
%95 = phi i64 [ %2, %6 ], [ %2, %4 ], [ %14, %92 ]
%96 = phi i64* [ %1, %6 ], [ %1, %4 ], [ %15, %92 ]
%97 = phi i64* [ inttoptr (i64 8464 to i64*), %6 ], [ inttoptr (i64 8464 to i64*), %4 ], [ %16, %92 ]
%98 = add i64 %95, -1
%99 = and i64 %95, 7
%100 = icmp eq i64 %99, 0
br i1 %100, label %112, label %101
101: ; preds = %94, %101
%102 = phi i64 [ %106, %101 ], [ %95, %94 ]
%103 = phi i64* [ %107, %101 ], [ %96, %94 ]
%104 = phi i64* [ %109, %101 ], [ %97, %94 ]
%105 = phi i64 [ %110, %101 ], [ 0, %94 ]
%106 = add i64 %102, -1
%107 = getelementptr inbounds i64, i64* %103, i64 1
%108 = load i64, i64* %103
%109 = getelementptr inbounds i64, i64* %104, i64 1
store i64 %108, i64* %104
%110 = add i64 %105, 1
%111 = icmp eq i64 %110, %99
br i1 %111, label %112, label %101
112: ; preds = %101, %94
%113 = phi i64* [ undef, %94 ], [ %107, %101 ]
%114 = phi i64 [ %95, %94 ], [ %106, %101 ]
%115 = phi i64* [ %96, %94 ], [ %107, %101 ]
%116 = phi i64* [ %97, %94 ], [ %109, %101 ]
%117 = icmp ult i64 %98, 7
br i1 %117, label %148, label %118
118: ; preds = %112, %118
%119 = phi i64 [ %143, %118 ], [ %114, %112 ]
%120 = phi i64* [ %144, %118 ], [ %115, %112 ]
%121 = phi i64* [ %146, %118 ], [ %116, %112 ]
%122 = getelementptr inbounds i64, i64* %120, i64 1
%123 = load i64, i64* %120
%124 = getelementptr inbounds i64, i64* %121, i64 1
store i64 %123, i64* %121
%125 = getelementptr inbounds i64, i64* %120, i64 2
%126 = load i64, i64* %122
%127 = getelementptr inbounds i64, i64* %121, i64 2
store i64 %126, i64* %124
%128 = getelementptr inbounds i64, i64* %120, i64 3
%129 = load i64, i64* %125
%130 = getelementptr inbounds i64, i64* %121, i64 3
store i64 %129, i64* %127
%131 = getelementptr inbounds i64, i64* %120, i64 4
%132 = load i64, i64* %128
%133 = getelementptr inbounds i64, i64* %121, i64 4
store i64 %132, i64* %130
%134 = getelementptr inbounds i64, i64* %120, i64 5
%135 = load i64, i64* %131
%136 = getelementptr inbounds i64, i64* %121, i64 5
store i64 %135, i64* %133
%137 = getelementptr inbounds i64, i64* %120, i64 6
%138 = load i64, i64* %134
%139 = getelementptr inbounds i64, i64* %121, i64 6
store i64 %138, i64* %136
%140 = getelementptr inbounds i64, i64* %120, i64 7
%141 = load i64, i64* %137
%142 = getelementptr inbounds i64, i64* %121, i64 7
store i64 %141, i64* %139
%143 = add i64 %119, -8
%144 = getelementptr inbounds i64, i64* %120, i64 8
%145 = load i64, i64* %140
%146 = getelementptr inbounds i64, i64* %121, i64 8
store i64 %145, i64* %142
%147 = icmp eq i64 %143, 0
br i1 %147, label %148, label %118
148: ; preds = %112, %118, %92, %0
%149 = phi i64* [ %1, %0 ], [ %15, %92 ], [ %113, %112 ], [ %144, %118 ]
store i64* %149, i64** inttoptr (i64 8448 to i64**)
ret void
}