double fdot(int D, double *x, double *y, double *z) {
  double sum, *stop;
  sum = 0.0;
  stop = x + D;
  while (x < stop)
    sum += *x++ * *y++ * *z++;
  return sum;
}


x86 assembly (clang, -O0):
<fdot>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x4(%rbp),%rcx
shl    $0x3,%rcx
add    %rcx,%rax
mov    %rax,-0x30(%rbp)
mov    -0x10(%rbp),%rax
cmp    -0x30(%rbp),%rax
jae    118c <fdot+0x8c>
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x10(%rbp)
movsd  (%rax),%xmm0
mov    -0x18(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x18(%rbp)
mulsd  (%rax),%xmm0
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x20(%rbp)
movsd  (%rax),%xmm2
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
jmp    112e <fdot+0x2e>
movsd  -0x28(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<fdot>:
test   %edi,%edi
jle    1145 <fdot+0x45>
movslq %edi,%rax
lea    (%rsi,%rax,8),%r8
xorpd  %xmm0,%xmm0
xor    %edi,%edi
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movsd  (%rsi,%rdi,1),%xmm1
mulsd  (%rdx,%rdi,1),%xmm1
mulsd  (%rcx,%rdi,1),%xmm1
addsd  %xmm1,%xmm0
lea    (%rsi,%rdi,1),%rax
add    $0x8,%rax
add    $0x8,%rdi
cmp    %r8,%rax
jb     1120 <fdot+0x20>
ret
xorps  %xmm0,%xmm0
ret

LLVM IR (-O0):
define double @fdot(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 double*
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
%11 = load double*, double** %6
%12 = load i32, i32* %5
%13 = sext i32 %12 to i64
%14 = getelementptr inbounds double, double* %11, i64 %13
store double* %14, double** %10
br label %15
15: ; preds = %19, %4
%16 = load double*, double** %6
%17 = load double*, double** %10
%18 = icmp ult double* %16, %17
br i1 %18, label %19, label %32
19: ; preds = %15
%20 = load double*, double** %6
%21 = getelementptr inbounds double, double* %20, i32 1
store double* %21, double** %6
%22 = load double, double* %20
%23 = load double*, double** %7
%24 = getelementptr inbounds double, double* %23, i32 1
store double* %24, double** %7
%25 = load double, double* %23
%26 = fmul double %22, %25
%27 = load double*, double** %8
%28 = getelementptr inbounds double, double* %27, i32 1
store double* %28, double** %8
%29 = load double, double* %27
%30 = load double, double* %9
%31 = call double @llvm.fmuladd.f64(double %26, double %29, double %30)
store double %31, double* %9
br label %15
32: ; preds = %15
%33 = load double, double* %9
ret double %33
}

LLVM IR (-O2):
define double @fdot(i32 %0, double* %1, double* nocapture %2, double* nocapture %3) {
%5 = sext i32 %0 to i64
%6 = getelementptr inbounds double, double* %1, i64 %5
%7 = icmp sgt i32 %0, 0
br i1 %7, label %8, label %22
8: ; preds = %4, %8
%9 = phi double* [ %13, %8 ], [ %1, %4 ]
%10 = phi double [ %20, %8 ], [ 0.000000e+00, %4 ]
%11 = phi double* [ %18, %8 ], [ %3, %4 ]
%12 = phi double* [ %15, %8 ], [ %2, %4 ]
%13 = getelementptr inbounds double, double* %9, i64 1
%14 = load double, double* %9
%15 = getelementptr inbounds double, double* %12, i64 1
%16 = load double, double* %12
%17 = fmul double %14, %16
%18 = getelementptr inbounds double, double* %11, i64 1
%19 = load double, double* %11
%20 = tail call double @llvm.fmuladd.f64(double %17, double %19, double %10)
%21 = icmp ult double* %13, %6
br i1 %21, label %8, label %22
22: ; preds = %8, %4
%23 = phi double [ 0.000000e+00, %4 ], [ %20, %8 ]
ret double %23
}