void copy(const double *a, int b, int e, double *d, int j) {
  while (e >= b)
    d[j++] = a[b++];
}


x86 assembly (clang, -O0):
<copy>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %rcx,-0x18(%rbp)
mov    %r8d,-0x1c(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0xc(%rbp),%eax
jl     1155 <copy+0x55>
mov    -0x8(%rbp),%rax
mov    -0xc(%rbp),%ecx
mov    %ecx,%edx
add    $0x1,%edx
mov    %edx,-0xc(%rbp)
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%edx
add    $0x1,%edx
mov    %edx,-0x1c(%rbp)
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
jmp    1116 <copy+0x16>
pop    %rbp
ret

x86 assembly (clang, -O2):
<copy>:
push   %r15
push   %r14
push   %rbx
mov    %edx,%r9d
sub    %esi,%r9d
jl     1286 <copy+0x186>
movslq %r8d,%r11
movslq %esi,%rsi
cmp    $0x3,%r9d
jb     11f6 <copy+0xf6>
lea    (%rcx,%r11,8),%rax
lea    (%rsi,%r9,1),%rbx
lea    (%rdi,%rbx,8),%rbx
add    $0x8,%rbx
cmp    %rbx,%rax
jae    114f <copy+0x4f>
lea    (%r11,%r9,1),%rax
lea    (%rcx,%rax,8),%rax
add    $0x8,%rax
lea    (%rdi,%rsi,8),%rbx
cmp    %rax,%rbx
jb     11f6 <copy+0xf6>
add    $0x1,%r9
mov    %r9,%r8
and    $0xfffffffffffffffc,%r8
lea    -0x4(%r8),%rax
mov    %rax,%r10
shr    $0x2,%r10
add    $0x1,%r10
test   %rax,%rax
je     128c <copy+0x18c>
mov    %r10,%rbx
and    $0xfffffffffffffffe,%rbx
lea    (%rdi,%rsi,8),%r14
add    $0x30,%r14
lea    (%rcx,%r11,8),%r15
add    $0x30,%r15
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
movups -0x30(%r14,%rax,8),%xmm0
movups -0x20(%r14,%rax,8),%xmm1
movups %xmm0,-0x30(%r15,%rax,8)
movups %xmm1,-0x20(%r15,%rax,8)
movups -0x10(%r14,%rax,8),%xmm0
movups (%r14,%rax,8),%xmm1
movups %xmm0,-0x10(%r15,%rax,8)
movups %xmm1,(%r15,%rax,8)
add    $0x8,%rax
add    $0xfffffffffffffffe,%rbx
jne    1190 <copy+0x90>
test   $0x1,%r10b
je     11e7 <copy+0xe7>
lea    (%rax,%rsi,1),%rbx
add    %r11,%rax
movups (%rdi,%rbx,8),%xmm0
movups 0x10(%rdi,%rbx,8),%xmm1
movups %xmm0,(%rcx,%rax,8)
movups %xmm1,0x10(%rcx,%rax,8)
cmp    %r8,%r9
je     1286 <copy+0x186>
add    %r8,%rsi
add    %r8,%r11
mov    %edx,%eax
sub    %esi,%eax
lea    0x1(%rax),%ebx
and    $0x3,%ebx
je     1228 <copy+0x128>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movsd  (%rdi,%rsi,8),%xmm0
add    $0x1,%rsi
movsd  %xmm0,(%rcx,%r11,8)
add    $0x1,%r11
add    $0xffffffff,%ebx
jne    1210 <copy+0x110>
cmp    $0x3,%eax
jb     1286 <copy+0x186>
sub    %esi,%edx
add    $0x1,%edx
lea    (%rdi,%rsi,8),%rax
add    $0x18,%rax
lea    (%rcx,%r11,8),%rcx
add    $0x18,%rcx
xor    %esi,%esi
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movsd  -0x18(%rax,%rsi,8),%xmm0
movsd  %xmm0,-0x18(%rcx,%rsi,8)
movsd  -0x10(%rax,%rsi,8),%xmm0
movsd  %xmm0,-0x10(%rcx,%rsi,8)
movsd  -0x8(%rax,%rsi,8),%xmm0
movsd  %xmm0,-0x8(%rcx,%rsi,8)
movsd  (%rax,%rsi,8),%xmm0
movsd  %xmm0,(%rcx,%rsi,8)
add    $0x4,%rsi
cmp    %esi,%edx
jne    1250 <copy+0x150>
pop    %rbx
pop    %r14
pop    %r15
ret
xor    %eax,%eax
test   $0x1,%r10b
jne    11ce <copy+0xce>
jmp    11e7 <copy+0xe7>

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

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