double scalar_product_of_vectors(int dim, double *vec_1, double *vec_2) {
  double result;
  result = 0.0;
  do {
    result += (*(vec_1++)) * (*(vec_2++));
  } while (--dim);
  return result;
}


x86 assembly (clang, -O0):
<scalar_product_of_vectors>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x20(%rbp)
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)
movsd  (%rax),%xmm2
movsd  -0x20(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x4(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x4(%rbp)
cmp    $0x0,%eax
jne    1117 <scalar_product_of_vectors+0x17>
movsd  -0x20(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<scalar_product_of_vectors>:
lea    -0x1(%rdi),%r8d
mov    %edi,%ecx
and    $0x3,%ecx
je     1145 <scalar_product_of_vectors+0x45>
xor    %eax,%eax
xorpd  %xmm0,%xmm0
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movsd  (%rsi),%xmm1
add    $0x8,%rsi
mulsd  (%rdx),%xmm1
add    $0x8,%rdx
addsd  %xmm1,%xmm0
add    $0x1,%eax
cmp    %eax,%ecx
jne    1120 <scalar_product_of_vectors+0x20>
sub    %eax,%edi
cmp    $0x3,%r8d
jae    114f <scalar_product_of_vectors+0x4f>
jmp    11a6 <scalar_product_of_vectors+0xa6>
xorpd  %xmm0,%xmm0
cmp    $0x3,%r8d
jb     11a6 <scalar_product_of_vectors+0xa6>
mov    %edi,%eax
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movsd  (%rsi,%rcx,8),%xmm1
movsd  0x8(%rsi,%rcx,8),%xmm2
mulsd  (%rdx,%rcx,8),%xmm1
mulsd  0x8(%rdx,%rcx,8),%xmm2
addsd  %xmm0,%xmm1
movsd  0x10(%rsi,%rcx,8),%xmm3
mulsd  0x10(%rdx,%rcx,8),%xmm3
addsd  %xmm1,%xmm2
movsd  0x18(%rsi,%rcx,8),%xmm0
mulsd  0x18(%rdx,%rcx,8),%xmm0
addsd  %xmm2,%xmm3
addsd  %xmm3,%xmm0
add    $0x4,%rcx
cmp    %ecx,%eax
jne    1160 <scalar_product_of_vectors+0x60>
ret

LLVM IR (-O0):
define double @scalar_product_of_vectors(i32 %0, double* %1, double* %2) {
%4 = alloca i32
%5 = alloca double*
%6 = alloca double*
%7 = alloca double
store i32 %0, i32* %4
store double* %1, double** %5
store double* %2, double** %6
store double 0.000000e+00, double* %7
br label %8
8: ; preds = %17, %3
%9 = load double*, double** %5
%10 = getelementptr inbounds double, double* %9, i32 1
store double* %10, double** %5
%11 = load double, double* %9
%12 = load double*, double** %6
%13 = getelementptr inbounds double, double* %12, i32 1
store double* %13, double** %6
%14 = load double, double* %12
%15 = load double, double* %7
%16 = call double @llvm.fmuladd.f64(double %11, double %14, double %15)
store double %16, double* %7
br label %17
17: ; preds = %8
%18 = load i32, i32* %4
%19 = add nsw i32 %18, -1
store i32 %19, i32* %4
%20 = icmp ne i32 %19, 0
br i1 %20, label %8, label %21
21: ; preds = %17
%22 = load double, double* %7
ret double %22
}

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