void extractNeigborhood4(const float *img, const int nx, const int x,
                         const int y, double z[16]) {
  static int idx[16] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};
  const float *r;
  int k, n;
  r = img + ((y - 1) * nx + x - 1);
  n = 0;
  for (k = 0; k < 4; k++) {
    int m;
    for (m = 0; m < 4; m++)
      z[idx[n++]] = r[m];
    r += nx;
  }
}


x86 assembly (clang, -O0):
<extractNeigborhood4>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %ecx,-0x14(%rbp)
mov    %r8,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
sub    $0x1,%ecx
imul   -0xc(%rbp),%ecx
add    -0x10(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
shl    $0x2,%rcx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
movl   $0x0,-0x30(%rbp)
movl   $0x0,-0x2c(%rbp)
cmpl   $0x4,-0x2c(%rbp)
jge    11c4 <extractNeigborhood4+0xc4>
movl   $0x0,-0x34(%rbp)
cmpl   $0x4,-0x34(%rbp)
jge    11a1 <extractNeigborhood4+0xa1>
mov    -0x28(%rbp),%rax
movslq -0x34(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
mov    -0x20(%rbp),%rax
mov    -0x30(%rbp),%ecx
mov    %ecx,%edx
add    $0x1,%edx
mov    %edx,-0x30(%rbp)
movslq %ecx,%rdx
lea    0x2ea6(%rip),%rcx
movslq (%rcx,%rdx,4),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    1156 <extractNeigborhood4+0x56>
mov    -0xc(%rbp),%ecx
mov    -0x28(%rbp),%rax
movslq %ecx,%rcx
shl    $0x2,%rcx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1145 <extractNeigborhood4+0x45>
pop    %rbp
ret

x86 assembly (clang, -O2):
<extractNeigborhood4>:
add    $0xffffffff,%ecx
imul   %esi,%ecx
lea    (%rdx,%rcx,1),%eax
add    $0xffffffff,%eax
movslq %eax,%rcx
lea    (%rdi,%rcx,4),%rdx
movslq %esi,%rax
movss  (%rdx,%rax,4),%xmm0
movss  (%rdi,%rcx,4),%xmm1
unpcklps %xmm0,%xmm1
movss  0x4(%rdi,%rcx,4),%xmm0
movss  0x8(%rdi,%rcx,4),%xmm2
cvtps2pd %xmm1,%xmm1
movss  0xc(%rdi,%rcx,4),%xmm3
movups %xmm1,(%r8)
movss  0x4(%rdx,%rax,4),%xmm1
unpcklps %xmm1,%xmm0
cvtps2pd %xmm0,%xmm0
movups %xmm0,0x20(%r8)
movss  0x8(%rdx,%rax,4),%xmm0
unpcklps %xmm0,%xmm2
cvtps2pd %xmm2,%xmm0
movups %xmm0,0x40(%r8)
movss  0xc(%rdx,%rax,4),%xmm0
unpcklps %xmm0,%xmm3
cvtps2pd %xmm3,%xmm0
lea    (%rdx,%rax,4),%rcx
movups %xmm0,0x60(%r8)
lea    (%rcx,%rax,4),%rdx
movss  (%rdx,%rax,4),%xmm0
movss  (%rcx,%rax,4),%xmm1
unpcklps %xmm0,%xmm1
movss  0x4(%rcx,%rax,4),%xmm0
movss  0x8(%rcx,%rax,4),%xmm2
movss  0xc(%rcx,%rax,4),%xmm3
cvtps2pd %xmm1,%xmm1
movups %xmm1,0x10(%r8)
movss  0x4(%rdx,%rax,4),%xmm1
unpcklps %xmm1,%xmm0
cvtps2pd %xmm0,%xmm0
movups %xmm0,0x30(%r8)
movss  0x8(%rdx,%rax,4),%xmm0
unpcklps %xmm0,%xmm2
cvtps2pd %xmm2,%xmm0
movups %xmm0,0x50(%r8)
movss  0xc(%rdx,%rax,4),%xmm0
unpcklps %xmm0,%xmm3
cvtps2pd %xmm3,%xmm0
movups %xmm0,0x70(%r8)
ret

LLVM IR (-O0):
@extractNeigborhood4.idx = internal global [16 x i32] [i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15]
define void @extractNeigborhood4(float* %0, i32 %1, i32 %2, i32 %3, double* %4) {
%6 = alloca float*
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca double*
%11 = alloca float*
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
store float* %0, float** %6
store i32 %1, i32* %7
store i32 %2, i32* %8
store i32 %3, i32* %9
store double* %4, double** %10
%15 = load float*, float** %6
%16 = load i32, i32* %9
%17 = sub nsw i32 %16, 1
%18 = load i32, i32* %7
%19 = mul nsw i32 %17, %18
%20 = load i32, i32* %8
%21 = add nsw i32 %19, %20
%22 = sub nsw i32 %21, 1
%23 = sext i32 %22 to i64
%24 = getelementptr inbounds float, float* %15, i64 %23
store float* %24, float** %11
store i32 0, i32* %13
store i32 0, i32* %12
br label %25
25: ; preds = %55, %5
%26 = load i32, i32* %12
%27 = icmp slt i32 %26, 4
br i1 %27, label %28, label %58
28: ; preds = %25
store i32 0, i32* %14
br label %29
29: ; preds = %47, %28
%30 = load i32, i32* %14
%31 = icmp slt i32 %30, 4
br i1 %31, label %32, label %50
32: ; preds = %29
%33 = load float*, float** %11
%34 = load i32, i32* %14
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds float, float* %33, i64 %35
%37 = load float, float* %36
%38 = fpext float %37 to double
%39 = load double*, double** %10
%40 = load i32, i32* %13
%41 = add nsw i32 %40, 1
store i32 %41, i32* %13
%42 = sext i32 %40 to i64
%43 = getelementptr inbounds [16 x i32], [16 x i32]* @extractNeigborhood4.idx, i64 0, i64 %42
%44 = load i32, i32* %43
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds double, double* %39, i64 %45
store double %38, double* %46
br label %47
47: ; preds = %32
%48 = load i32, i32* %14
%49 = add nsw i32 %48, 1
store i32 %49, i32* %14
br label %29
50: ; preds = %29
%51 = load i32, i32* %7
%52 = load float*, float** %11
%53 = sext i32 %51 to i64
%54 = getelementptr inbounds float, float* %52, i64 %53
store float* %54, float** %11
br label %55
55: ; preds = %50
%56 = load i32, i32* %12
%57 = add nsw i32 %56, 1
store i32 %57, i32* %12
br label %25
58: ; preds = %25
ret void
}

LLVM IR (-O2):
define void @extractNeigborhood4(float* nocapture %0, i32 %1, i32 %2, i32 %3, double* nocapture writeonly %4) {
%6 = add nsw i32 %3, -1
%7 = mul nsw i32 %6, %1
%8 = add i32 %2, -1
%9 = add i32 %8, %7
%10 = sext i32 %9 to i64
%11 = getelementptr inbounds float, float* %0, i64 %10
%12 = sext i32 %1 to i64
%13 = load float, float* %11
%14 = getelementptr inbounds float, float* %11, i64 1
%15 = load float, float* %14
%16 = getelementptr inbounds double, double* %4, i64 4
%17 = getelementptr inbounds float, float* %11, i64 2
%18 = load float, float* %17
%19 = getelementptr inbounds double, double* %4, i64 8
%20 = getelementptr inbounds float, float* %11, i64 3
%21 = load float, float* %20
%22 = getelementptr inbounds double, double* %4, i64 12
%23 = getelementptr inbounds float, float* %11, i64 %12
%24 = load float, float* %23
%25 = insertelement <2 x float> poison, float %13, i64 0
%26 = insertelement <2 x float> %25, float %24, i64 1
%27 = fpext <2 x float> %26 to <2 x double>
%28 = bitcast double* %4 to <2 x double>*
store <2 x double> %27, <2 x double>* %28
%29 = getelementptr inbounds float, float* %23, i64 1
%30 = load float, float* %29
%31 = insertelement <2 x float> poison, float %15, i64 0
%32 = insertelement <2 x float> %31, float %30, i64 1
%33 = fpext <2 x float> %32 to <2 x double>
%34 = bitcast double* %16 to <2 x double>*
store <2 x double> %33, <2 x double>* %34
%35 = getelementptr inbounds float, float* %23, i64 2
%36 = load float, float* %35
%37 = insertelement <2 x float> poison, float %18, i64 0
%38 = insertelement <2 x float> %37, float %36, i64 1
%39 = fpext <2 x float> %38 to <2 x double>
%40 = bitcast double* %19 to <2 x double>*
store <2 x double> %39, <2 x double>* %40
%41 = getelementptr inbounds float, float* %23, i64 3
%42 = load float, float* %41
%43 = insertelement <2 x float> poison, float %21, i64 0
%44 = insertelement <2 x float> %43, float %42, i64 1
%45 = fpext <2 x float> %44 to <2 x double>
%46 = bitcast double* %22 to <2 x double>*
store <2 x double> %45, <2 x double>* %46
%47 = getelementptr inbounds float, float* %23, i64 %12
%48 = load float, float* %47
%49 = getelementptr inbounds double, double* %4, i64 2
%50 = getelementptr inbounds float, float* %47, i64 1
%51 = load float, float* %50
%52 = getelementptr inbounds double, double* %4, i64 6
%53 = getelementptr inbounds float, float* %47, i64 2
%54 = load float, float* %53
%55 = getelementptr inbounds double, double* %4, i64 10
%56 = getelementptr inbounds float, float* %47, i64 3
%57 = load float, float* %56
%58 = getelementptr inbounds double, double* %4, i64 14
%59 = getelementptr inbounds float, float* %47, i64 %12
%60 = load float, float* %59
%61 = insertelement <2 x float> poison, float %48, i64 0
%62 = insertelement <2 x float> %61, float %60, i64 1
%63 = fpext <2 x float> %62 to <2 x double>
%64 = bitcast double* %49 to <2 x double>*
store <2 x double> %63, <2 x double>* %64
%65 = getelementptr inbounds float, float* %59, i64 1
%66 = load float, float* %65
%67 = insertelement <2 x float> poison, float %51, i64 0
%68 = insertelement <2 x float> %67, float %66, i64 1
%69 = fpext <2 x float> %68 to <2 x double>
%70 = bitcast double* %52 to <2 x double>*
store <2 x double> %69, <2 x double>* %70
%71 = getelementptr inbounds float, float* %59, i64 2
%72 = load float, float* %71
%73 = insertelement <2 x float> poison, float %54, i64 0
%74 = insertelement <2 x float> %73, float %72, i64 1
%75 = fpext <2 x float> %74 to <2 x double>
%76 = bitcast double* %55 to <2 x double>*
store <2 x double> %75, <2 x double>* %76
%77 = getelementptr inbounds float, float* %59, i64 3
%78 = load float, float* %77
%79 = insertelement <2 x float> poison, float %57, i64 0
%80 = insertelement <2 x float> %79, float %78, i64 1
%81 = fpext <2 x float> %80 to <2 x double>
%82 = bitcast double* %58 to <2 x double>*
store <2 x double> %81, <2 x double>* %82
ret void
}