void _lengthscale_grads_unsafe(int N, int M, int Q, double *tmp, double *X,
                               double *X2, double *grad) {
  int n, m, nm, q, nQ, mQ;
  double dist;
#pragma omp parallel for private(n, m, nm, q, nQ, mQ, dist)
  for (nm = 0; nm < (N * M); nm++) {
    n = nm / M;
    m = nm % M;
    nQ = n * Q;
    mQ = m * Q;
    for (q = 0; q < Q; q++) {
      dist = X[nQ + q] - X2[mQ + q];
      grad[q] += tmp[nm] * dist * dist;
    }
  }
}


x86 assembly (clang, -O0):
<_lengthscale_grads_unsafe>:
push   %rbp
mov    %rsp,%rbp
mov    0x10(%rbp),%rax
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %edx,-0xc(%rbp)
mov    %rcx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
movl   $0x0,-0x34(%rbp)
mov    -0x34(%rbp),%eax
mov    -0x4(%rbp),%ecx
imul   -0x8(%rbp),%ecx
cmp    %ecx,%eax
jge    11ec <_lengthscale_grads_unsafe+0xec>
mov    -0x34(%rbp),%eax
cltd
idivl  -0x8(%rbp)
mov    %eax,-0x2c(%rbp)
mov    -0x34(%rbp),%eax
cltd
idivl  -0x8(%rbp)
mov    %edx,-0x30(%rbp)
mov    -0x2c(%rbp),%eax
imul   -0xc(%rbp),%eax
mov    %eax,-0x3c(%rbp)
mov    -0x30(%rbp),%eax
imul   -0xc(%rbp),%eax
mov    %eax,-0x40(%rbp)
movl   $0x0,-0x38(%rbp)
mov    -0x38(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    11d9 <_lengthscale_grads_unsafe+0xd9>
mov    -0x20(%rbp),%rax
mov    -0x3c(%rbp),%ecx
add    -0x38(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x28(%rbp),%rax
mov    -0x40(%rbp),%ecx
add    -0x38(%rbp),%ecx
movslq %ecx,%rcx
subsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x18(%rbp),%rax
movslq -0x34(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mulsd  -0x48(%rbp),%xmm0
movsd  -0x48(%rbp),%xmm2
mov    0x10(%rbp),%rax
movslq -0x38(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x38(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x38(%rbp)
jmp    1165 <_lengthscale_grads_unsafe+0x65>
jmp    11de <_lengthscale_grads_unsafe+0xde>
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    1124 <_lengthscale_grads_unsafe+0x24>
pop    %rbp
ret

x86 assembly (clang, -O2):
<_lengthscale_grads_unsafe>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %r9,-0x50(%rsp)
imul   %esi,%edi
test   %edi,%edi
jle    13d8 <_lengthscale_grads_unsafe+0x2d8>
mov    %edx,%r10d
mov    0x38(%rsp),%r11
mov    %edi,%r14d
mov    %edx,%ebx
lea    (%r11,%rbx,8),%rax
mov    %rax,-0x10(%rsp)
lea    (%r8,%rbx,8),%rax
mov    %rax,-0x18(%rsp)
mov    -0x50(%rsp),%rax
lea    (%rax,%rbx,8),%rdx
mov    %rdx,-0x20(%rsp)
mov    %ebx,%edx
and    $0xfffffffc,%edx
mov    %rdx,-0x38(%rsp)
mov    %rbx,%rdx
neg    %rdx
mov    %rdx,-0x8(%rsp)
lea    0x10(%r8),%rdx
mov    %rdx,-0x40(%rsp)
lea    0x10(%rax),%rdx
mov    %rdx,-0x48(%rsp)
lea    0x0(,%rbx,8),%r13
and    $0xffffffffffffffe0,%r13
add    $0x8,%rax
mov    %rax,-0x28(%rsp)
lea    0x8(%r8),%rax
mov    %rax,-0x30(%rsp)
xor    %edi,%edi
mov    %esi,-0x64(%rsp)
mov    %r14,-0x58(%rsp)
mov    %r8,-0x60(%rsp)
jmp    11ad <_lengthscale_grads_unsafe+0xad>
xchg   %ax,%ax
add    $0x1,%rdi
cmp    %r14,%rdi
je     13d8 <_lengthscale_grads_unsafe+0x2d8>
test   %r10d,%r10d
jle    11a0 <_lengthscale_grads_unsafe+0xa0>
mov    %edi,%eax
cltd
idiv   %esi
imul   %r10d,%edx
imul   %r10d,%eax
movslq %eax,%r15
movslq %edx,%r9
cmp    $0x4,%r10d
jae    11e0 <_lengthscale_grads_unsafe+0xe0>
xor    %r12d,%r12d
jmp    1320 <_lengthscale_grads_unsafe+0x220>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
lea    (%rcx,%rdi,8),%rax
add    $0x8,%rax
lea    (%r8,%r15,8),%rdx
mov    -0x18(%rsp),%rsi
lea    (%rsi,%r15,8),%rbp
cmp    %r11,%rbp
seta   %r8b
mov    -0x20(%rsp),%rsi
lea    (%rsi,%r9,8),%rbp
mov    -0x10(%rsp),%r14
cmp    %r14,%rdx
setb   %sil
cmp    %r11,%rbp
mov    -0x50(%rsp),%rdx
lea    (%rdx,%r9,8),%rbp
seta   %dl
cmp    %r14,%rbp
setb   %r12b
cmp    %r11,%rax
seta   %al
lea    (%rcx,%rdi,8),%rbp
cmp    %r14,%rbp
setb   %bpl
test   %sil,%r8b
jne    1305 <_lengthscale_grads_unsafe+0x205>
and    %r12b,%dl
jne    1305 <_lengthscale_grads_unsafe+0x205>
mov    $0x0,%r12d
and    %bpl,%al
mov    -0x60(%rsp),%r8
mov    -0x64(%rsp),%esi
mov    -0x58(%rsp),%r14
jne    1320 <_lengthscale_grads_unsafe+0x220>
movsd  (%rcx,%rdi,8),%xmm0
unpcklpd %xmm0,%xmm0
mov    -0x40(%rsp),%rax
lea    (%rax,%r15,8),%rbp
mov    -0x48(%rsp),%rax
lea    (%rax,%r9,8),%rax
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movupd -0x10(%rbp,%rdx,1),%xmm1
movupd 0x0(%rbp,%rdx,1),%xmm2
movupd -0x10(%rax,%rdx,1),%xmm3
subpd  %xmm3,%xmm1
movupd (%rax,%rdx,1),%xmm3
subpd  %xmm3,%xmm2
movapd %xmm0,%xmm3
mulpd  %xmm1,%xmm3
movapd %xmm0,%xmm4
mulpd  %xmm2,%xmm4
movupd (%r11,%rdx,1),%xmm5
movupd 0x10(%r11,%rdx,1),%xmm6
mulpd  %xmm1,%xmm3
addpd  %xmm5,%xmm3
mulpd  %xmm2,%xmm4
addpd  %xmm6,%xmm4
movupd %xmm3,(%r11,%rdx,1)
movupd %xmm4,0x10(%r11,%rdx,1)
add    $0x20,%rdx
cmp    %rdx,%r13
jne    1290 <_lengthscale_grads_unsafe+0x190>
mov    -0x38(%rsp),%rax
mov    %rax,%r12
cmp    %rbx,%rax
je     11a0 <_lengthscale_grads_unsafe+0xa0>
jmp    1320 <_lengthscale_grads_unsafe+0x220>
xor    %r12d,%r12d
mov    -0x60(%rsp),%r8
mov    -0x64(%rsp),%esi
mov    -0x58(%rsp),%r14
cs nopw 0x0(%rax,%rax,1)
mov    %r12,%rbp
test   $0x1,%bl
je     1360 <_lengthscale_grads_unsafe+0x260>
lea    (%r12,%r15,1),%rax
movsd  (%r8,%rax,8),%xmm0
lea    (%r12,%r9,1),%rax
mov    -0x50(%rsp),%rdx
subsd  (%rdx,%rax,8),%xmm0
movsd  (%rcx,%rdi,8),%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
addsd  (%r11,%r12,8),%xmm1
movsd  %xmm1,(%r11,%r12,8)
mov    %r12,%rbp
or     $0x1,%rbp
not    %r12
cmp    -0x8(%rsp),%r12
je     11a0 <_lengthscale_grads_unsafe+0xa0>
mov    -0x28(%rsp),%rax
lea    (%rax,%r9,8),%rax
mov    -0x30(%rsp),%rdx
lea    (%rdx,%r15,8),%rdx
movsd  -0x8(%rdx,%rbp,8),%xmm0
subsd  -0x8(%rax,%rbp,8),%xmm0
movsd  (%rcx,%rdi,8),%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
addsd  (%r11,%rbp,8),%xmm1
movsd  %xmm1,(%r11,%rbp,8)
movsd  (%rdx,%rbp,8),%xmm0
subsd  (%rax,%rbp,8),%xmm0
movsd  (%rcx,%rdi,8),%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
addsd  0x8(%r11,%rbp,8),%xmm1
movsd  %xmm1,0x8(%r11,%rbp,8)
add    $0x2,%rbp
cmp    %rbp,%rbx
jne    1380 <_lengthscale_grads_unsafe+0x280>
jmp    11a0 <_lengthscale_grads_unsafe+0xa0>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @_lengthscale_grads_unsafe(i32 %0, i32 %1, i32 %2, double* %3, double* %4, double* %5, double* %6) {
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca double*
%12 = alloca double*
%13 = alloca double*
%14 = alloca double*
%15 = alloca i32
%16 = alloca i32
%17 = alloca i32
%18 = alloca i32
%19 = alloca i32
%20 = alloca i32
%21 = alloca double
store i32 %0, i32* %8
store i32 %1, i32* %9
store i32 %2, i32* %10
store double* %3, double** %11
store double* %4, double** %12
store double* %5, double** %13
store double* %6, double** %14
store i32 0, i32* %17
br label %22
22: ; preds = %79, %7
%23 = load i32, i32* %17
%24 = load i32, i32* %8
%25 = load i32, i32* %9
%26 = mul nsw i32 %24, %25
%27 = icmp slt i32 %23, %26
br i1 %27, label %28, label %82
28: ; preds = %22
%29 = load i32, i32* %17
%30 = load i32, i32* %9
%31 = sdiv i32 %29, %30
store i32 %31, i32* %15
%32 = load i32, i32* %17
%33 = load i32, i32* %9
%34 = srem i32 %32, %33
store i32 %34, i32* %16
%35 = load i32, i32* %15
%36 = load i32, i32* %10
%37 = mul nsw i32 %35, %36
store i32 %37, i32* %19
%38 = load i32, i32* %16
%39 = load i32, i32* %10
%40 = mul nsw i32 %38, %39
store i32 %40, i32* %20
store i32 0, i32* %18
br label %41
41: ; preds = %75, %28
%42 = load i32, i32* %18
%43 = load i32, i32* %10
%44 = icmp slt i32 %42, %43
br i1 %44, label %45, label %78
45: ; preds = %41
%46 = load double*, double** %12
%47 = load i32, i32* %19
%48 = load i32, i32* %18
%49 = add nsw i32 %47, %48
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds double, double* %46, i64 %50
%52 = load double, double* %51
%53 = load double*, double** %13
%54 = load i32, i32* %20
%55 = load i32, i32* %18
%56 = add nsw i32 %54, %55
%57 = sext i32 %56 to i64
%58 = getelementptr inbounds double, double* %53, i64 %57
%59 = load double, double* %58
%60 = fsub double %52, %59
store double %60, double* %21
%61 = load double*, double** %11
%62 = load i32, i32* %17
%63 = sext i32 %62 to i64
%64 = getelementptr inbounds double, double* %61, i64 %63
%65 = load double, double* %64
%66 = load double, double* %21
%67 = fmul double %65, %66
%68 = load double, double* %21
%69 = load double*, double** %14
%70 = load i32, i32* %18
%71 = sext i32 %70 to i64
%72 = getelementptr inbounds double, double* %69, i64 %71
%73 = load double, double* %72
%74 = call double @llvm.fmuladd.f64(double %67, double %68, double %73)
store double %74, double* %72
br label %75
75: ; preds = %45
%76 = load i32, i32* %18
%77 = add nsw i32 %76, 1
store i32 %77, i32* %18
br label %41
78: ; preds = %41
br label %79
79: ; preds = %78
%80 = load i32, i32* %17
%81 = add nsw i32 %80, 1
store i32 %81, i32* %17
br label %22
82: ; preds = %22
ret void
}

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