double kinetic_energy_out_of_plane(int num_ptcls, const double *x,
                                   const double *v, double mass) {
  double energy = 0.0;
  int i;
  for (i = 0; i < num_ptcls; ++i) {
    energy += 0.5 * mass * v[3 * i + 2] * v[3 * i + 2];
  }
  return energy;
}


x86 assembly (clang, -O0):
<kinetic_energy_out_of_plane>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movsd  %xmm0,-0x20(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1182 <kinetic_energy_out_of_plane+0x82>
movsd  0xec9(%rip),%xmm0
mulsd  -0x20(%rbp),%xmm0
mov    -0x18(%rbp),%rax
imul   $0x3,-0x2c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mulsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
imul   $0x3,-0x2c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1123 <kinetic_energy_out_of_plane+0x23>
movsd  -0x28(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<kinetic_energy_out_of_plane>:
test   %edi,%edi
jle    111e <kinetic_energy_out_of_plane+0x1e>
mulsd  0xef4(%rip),%xmm0
mov    %edi,%eax
cmp    $0x1,%edi
jne    1124 <kinetic_energy_out_of_plane+0x24>
xorpd  %xmm1,%xmm1
mov    $0x2,%ecx
jmp    1175 <kinetic_energy_out_of_plane+0x75>
xorpd  %xmm1,%xmm1
jmp    1179 <kinetic_energy_out_of_plane+0x79>
mov    %eax,%esi
and    $0xfffffffe,%esi
xorpd  %xmm1,%xmm1
mov    $0x2,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movsd  (%rdx,%rcx,8),%xmm2
movsd  0x18(%rdx,%rcx,8),%xmm3
movapd %xmm0,%xmm4
mulsd  %xmm2,%xmm4
mulsd  %xmm2,%xmm4
addsd  %xmm1,%xmm4
movapd %xmm0,%xmm1
mulsd  %xmm3,%xmm1
mulsd  %xmm3,%xmm1
addsd  %xmm4,%xmm1
add    $0x6,%rcx
add    $0xfffffffffffffffe,%rsi
jne    1140 <kinetic_energy_out_of_plane+0x40>
test   $0x1,%al
jne    117e <kinetic_energy_out_of_plane+0x7e>
movapd %xmm1,%xmm0
ret
movsd  (%rdx,%rcx,8),%xmm2
mulsd  %xmm2,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
ret

LLVM IR (-O0):
define double @kinetic_energy_out_of_plane(i32 %0, double* %1, double* %2, double %3) {
%5 = alloca i32
%6 = alloca double*
%7 = alloca double*
%8 = alloca double
%9 = alloca double
%10 = alloca i32
store i32 %0, i32* %5
store double* %1, double** %6
store double* %2, double** %7
store double %3, double* %8
store double 0.000000e+00, double* %9
store i32 0, i32* %10
br label %11
11: ; preds = %35, %4
%12 = load i32, i32* %10
%13 = load i32, i32* %5
%14 = icmp slt i32 %12, %13
br i1 %14, label %15, label %38
15: ; preds = %11
%16 = load double, double* %8
%17 = fmul double 5.000000e-01, %16
%18 = load double*, double** %7
%19 = load i32, i32* %10
%20 = mul nsw i32 3, %19
%21 = add nsw i32 %20, 2
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds double, double* %18, i64 %22
%24 = load double, double* %23
%25 = fmul double %17, %24
%26 = load double*, double** %7
%27 = load i32, i32* %10
%28 = mul nsw i32 3, %27
%29 = add nsw i32 %28, 2
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds double, double* %26, i64 %30
%32 = load double, double* %31
%33 = load double, double* %9
%34 = call double @llvm.fmuladd.f64(double %25, double %32, double %33)
store double %34, double* %9
br label %35
35: ; preds = %15
%36 = load i32, i32* %10
%37 = add nsw i32 %36, 1
store i32 %37, i32* %10
br label %11
38: ; preds = %11
%39 = load double, double* %9
ret double %39
}

LLVM IR (-O2):
define double @kinetic_energy_out_of_plane(i32 %0, double* nocapture readnone %1, double* nocapture %2, double %3) {
%5 = icmp sgt i32 %0, 0
br i1 %5, label %6, label %46
6: ; preds = %4
%7 = fmul double %3, 5.000000e-01
%8 = zext i32 %0 to i64
%9 = and i64 %8, 1
%10 = icmp eq i32 %0, 1
br i1 %10, label %36, label %11
11: ; preds = %6
%12 = and i64 %8, 4294967294
br label %13
13: ; preds = %13, %11
%14 = phi i64 [ 0, %11 ], [ %30, %13 ]
%15 = phi double [ 0.000000e+00, %11 ], [ %29, %13 ]
%16 = phi i64 [ 0, %11 ], [ %31, %13 ]
%17 = mul nuw nsw i64 %14, 3
%18 = add nuw nsw i64 %17, 2
%19 = getelementptr inbounds double, double* %2, i64 %18
%20 = load double, double* %19
%21 = fmul double %7, %20
%22 = tail call double @llvm.fmuladd.f64(double %21, double %20, double %15)
%23 = or i64 %14, 1
%24 = mul nuw nsw i64 %23, 3
%25 = add nuw nsw i64 %24, 2
%26 = getelementptr inbounds double, double* %2, i64 %25
%27 = load double, double* %26
%28 = fmul double %7, %27
%29 = tail call double @llvm.fmuladd.f64(double %28, double %27, double %22)
%30 = add nuw nsw i64 %14, 2
%31 = add i64 %16, 2
%32 = icmp eq i64 %31, %12
br i1 %32, label %33, label %13
33: ; preds = %13
%34 = mul i64 %30, 3
%35 = add i64 %34, 2
br label %36
36: ; preds = %33, %6
%37 = phi double [ undef, %6 ], [ %29, %33 ]
%38 = phi i64 [ 2, %6 ], [ %35, %33 ]
%39 = phi double [ 0.000000e+00, %6 ], [ %29, %33 ]
%40 = icmp eq i64 %9, 0
br i1 %40, label %46, label %41
41: ; preds = %36
%42 = getelementptr inbounds double, double* %2, i64 %38
%43 = load double, double* %42
%44 = fmul double %7, %43
%45 = tail call double @llvm.fmuladd.f64(double %44, double %43, double %39)
br label %46
46: ; preds = %41, %36, %4
%47 = phi double [ 0.000000e+00, %4 ], [ %37, %36 ], [ %45, %41 ]
ret double %47
}