double silk_inner_product_FLP(const float *data1, const float *data2,
                              int dataSize) {
  int i;
  double result;
  result = 0.0;
  for (i = 0; i < dataSize - 3; i += 4) {
    result += data1[i + 0] * (double)data2[i + 0] +
              data1[i + 1] * (double)data2[i + 1] +
              data1[i + 2] * (double)data2[i + 2] +
              data1[i + 3] * (double)data2[i + 3];
  }
  for (; i < dataSize; i++) {
    result += data1[i] * (double)data2[i];
  }
  return result;
}


x86 assembly (clang, -O0):
<silk_inner_product_FLP>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x20(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x3,%ecx
cmp    %ecx,%eax
jge    1213 <silk_inner_product_FLP+0x113>
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm1
cvtss2sd %xmm1,%xmm2
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm1
cvtss2sd %xmm1,%xmm1
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm3
cvtss2sd %xmm3,%xmm3
mulsd  %xmm3,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm1
cvtss2sd %xmm1,%xmm1
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm2
cvtss2sd %xmm2,%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
movss  (%rax,%rcx,4),%xmm2
cvtss2sd %xmm2,%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x18(%rbp),%eax
add    $0x4,%eax
mov    %eax,-0x18(%rbp)
jmp    111e <silk_inner_product_FLP+0x1e>
jmp    1218 <silk_inner_product_FLP+0x118>
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1266 <silk_inner_product_FLP+0x166>
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm1
cvtss2sd %xmm1,%xmm2
movsd  -0x20(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1218 <silk_inner_product_FLP+0x118>
movsd  -0x20(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<silk_inner_product_FLP>:
cmp    $0x4,%edx
jl     11bd <silk_inner_product_FLP+0xbd>
lea    -0x3(%rdx),%eax
xorpd  %xmm1,%xmm1
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movss  (%rdi,%rcx,4),%xmm0
movss  0x4(%rdi,%rcx,4),%xmm2
cvtss2sd %xmm0,%xmm0
movss  (%rsi,%rcx,4),%xmm3
movss  0x4(%rsi,%rcx,4),%xmm4
cvtss2sd %xmm3,%xmm3
mulsd  %xmm0,%xmm3
xorps  %xmm0,%xmm0
cvtss2sd %xmm2,%xmm0
xorps  %xmm2,%xmm2
cvtss2sd %xmm4,%xmm2
mulsd  %xmm0,%xmm2
addsd  %xmm3,%xmm2
movss  0x8(%rdi,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
movss  0x8(%rsi,%rcx,4),%xmm3
cvtss2sd %xmm3,%xmm3
mulsd  %xmm0,%xmm3
addsd  %xmm2,%xmm3
movss  0xc(%rdi,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
movss  0xc(%rsi,%rcx,4),%xmm2
cvtss2sd %xmm2,%xmm2
mulsd  %xmm0,%xmm2
addsd  %xmm3,%xmm2
addsd  %xmm2,%xmm1
add    $0x4,%rcx
cmp    %rax,%rcx
jb     1120 <silk_inner_product_FLP+0x20>
cmp    %edx,%ecx
jge    11c7 <silk_inner_product_FLP+0xc7>
mov    %ecx,%eax
mov    %edx,%r8d
sub    %ecx,%edx
mov    %rax,%rcx
not    %rcx
test   $0x1,%dl
jne    11cc <silk_inner_product_FLP+0xcc>
add    %r8,%rcx
jne    11f6 <silk_inner_product_FLP+0xf6>
jmp    1245 <silk_inner_product_FLP+0x145>
xorpd  %xmm1,%xmm1
xor    %ecx,%ecx
cmp    %edx,%ecx
jl     11a1 <silk_inner_product_FLP+0xa1>
movapd %xmm1,%xmm0
ret
movss  (%rdi,%rax,4),%xmm0
xorps  %xmm2,%xmm2
cvtss2sd %xmm0,%xmm2
movss  (%rsi,%rax,4),%xmm0
cvtss2sd %xmm0,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
add    $0x1,%rax
movapd %xmm0,%xmm1
add    %r8,%rcx
je     1245 <silk_inner_product_FLP+0x145>
movapd %xmm1,%xmm0
nopw   0x0(%rax,%rax,1)
movss  (%rdi,%rax,4),%xmm1
movss  0x4(%rdi,%rax,4),%xmm2
cvtss2sd %xmm1,%xmm1
movss  (%rsi,%rax,4),%xmm3
movss  0x4(%rsi,%rax,4),%xmm4
cvtss2sd %xmm3,%xmm3
mulsd  %xmm1,%xmm3
addsd  %xmm0,%xmm3
xorps  %xmm1,%xmm1
cvtss2sd %xmm2,%xmm1
xorps  %xmm0,%xmm0
cvtss2sd %xmm4,%xmm0
mulsd  %xmm1,%xmm0
addsd  %xmm3,%xmm0
add    $0x2,%rax
cmp    %rax,%r8
jne    1200 <silk_inner_product_FLP+0x100>
ret

LLVM IR (-O0):
define double @silk_inner_product_FLP(float* %0, float* %1, i32 %2) {
%4 = alloca float*
%5 = alloca float*
%6 = alloca i32
%7 = alloca i32
%8 = alloca double
store float* %0, float** %4
store float* %1, float** %5
store i32 %2, i32* %6
store double 0.000000e+00, double* %8
store i32 0, i32* %7
br label %9
9: ; preds = %77, %3
%10 = load i32, i32* %7
%11 = load i32, i32* %6
%12 = sub nsw i32 %11, 3
%13 = icmp slt i32 %10, %12
br i1 %13, label %14, label %80
14: ; preds = %9
%15 = load float*, float** %4
%16 = load i32, i32* %7
%17 = add nsw i32 %16, 0
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds float, float* %15, i64 %18
%20 = load float, float* %19
%21 = fpext float %20 to double
%22 = load float*, float** %5
%23 = load i32, i32* %7
%24 = add nsw i32 %23, 0
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds float, float* %22, i64 %25
%27 = load float, float* %26
%28 = fpext float %27 to double
%29 = load float*, float** %4
%30 = load i32, i32* %7
%31 = add nsw i32 %30, 1
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds float, float* %29, i64 %32
%34 = load float, float* %33
%35 = fpext float %34 to double
%36 = load float*, float** %5
%37 = load i32, i32* %7
%38 = add nsw i32 %37, 1
%39 = sext i32 %38 to i64
%40 = getelementptr inbounds float, float* %36, i64 %39
%41 = load float, float* %40
%42 = fpext float %41 to double
%43 = fmul double %35, %42
%44 = call double @llvm.fmuladd.f64(double %21, double %28, double %43)
%45 = load float*, float** %4
%46 = load i32, i32* %7
%47 = add nsw i32 %46, 2
%48 = sext i32 %47 to i64
%49 = getelementptr inbounds float, float* %45, i64 %48
%50 = load float, float* %49
%51 = fpext float %50 to double
%52 = load float*, float** %5
%53 = load i32, i32* %7
%54 = add nsw i32 %53, 2
%55 = sext i32 %54 to i64
%56 = getelementptr inbounds float, float* %52, i64 %55
%57 = load float, float* %56
%58 = fpext float %57 to double
%59 = call double @llvm.fmuladd.f64(double %51, double %58, double %44)
%60 = load float*, float** %4
%61 = load i32, i32* %7
%62 = add nsw i32 %61, 3
%63 = sext i32 %62 to i64
%64 = getelementptr inbounds float, float* %60, i64 %63
%65 = load float, float* %64
%66 = fpext float %65 to double
%67 = load float*, float** %5
%68 = load i32, i32* %7
%69 = add nsw i32 %68, 3
%70 = sext i32 %69 to i64
%71 = getelementptr inbounds float, float* %67, i64 %70
%72 = load float, float* %71
%73 = fpext float %72 to double
%74 = call double @llvm.fmuladd.f64(double %66, double %73, double %59)
%75 = load double, double* %8
%76 = fadd double %75, %74
store double %76, double* %8
br label %77
77: ; preds = %14
%78 = load i32, i32* %7
%79 = add nsw i32 %78, 4
store i32 %79, i32* %7
br label %9
80: ; preds = %9
br label %81
81: ; preds = %100, %80
%82 = load i32, i32* %7
%83 = load i32, i32* %6
%84 = icmp slt i32 %82, %83
br i1 %84, label %85, label %103
85: ; preds = %81
%86 = load float*, float** %4
%87 = load i32, i32* %7
%88 = sext i32 %87 to i64
%89 = getelementptr inbounds float, float* %86, i64 %88
%90 = load float, float* %89
%91 = fpext float %90 to double
%92 = load float*, float** %5
%93 = load i32, i32* %7
%94 = sext i32 %93 to i64
%95 = getelementptr inbounds float, float* %92, i64 %94
%96 = load float, float* %95
%97 = fpext float %96 to double
%98 = load double, double* %8
%99 = call double @llvm.fmuladd.f64(double %91, double %97, double %98)
store double %99, double* %8
br label %100
100: ; preds = %85
%101 = load i32, i32* %7
%102 = add nsw i32 %101, 1
store i32 %102, i32* %7
br label %81
103: ; preds = %81
%104 = load double, double* %8
ret double %104
}

LLVM IR (-O2):
define double @silk_inner_product_FLP(float* nocapture %0, float* nocapture %1, i32 %2) {
%4 = icmp sgt i32 %2, 3
br i1 %4, label %5, label %10
5: ; preds = %3
%6 = add nsw i32 %2, -3
%7 = zext i32 %6 to i64
br label %36
8: ; preds = %36
%9 = trunc i64 %71 to i32
br label %10
10: ; preds = %8, %3
%11 = phi i32 [ 0, %3 ], [ %9, %8 ]
%12 = phi double [ 0.000000e+00, %3 ], [ %70, %8 ]
%13 = icmp slt i32 %11, %2
br i1 %13, label %14, label %93
14: ; preds = %10
%15 = zext i32 %11 to i64
%16 = zext i32 %2 to i64
%17 = sub nsw i64 %16, %15
%18 = xor i64 %15, -1
%19 = and i64 %17, 1
%20 = icmp eq i64 %19, 0
br i1 %20, label %30, label %21
21: ; preds = %14
%22 = getelementptr inbounds float, float* %0, i64 %15
%23 = load float, float* %22
%24 = fpext float %23 to double
%25 = getelementptr inbounds float, float* %1, i64 %15
%26 = load float, float* %25
%27 = fpext float %26 to double
%28 = tail call double @llvm.fmuladd.f64(double %24, double %27, double %12)
%29 = add nuw nsw i64 %15, 1
br label %30
30: ; preds = %21, %14
%31 = phi double [ undef, %14 ], [ %28, %21 ]
%32 = phi i64 [ %15, %14 ], [ %29, %21 ]
%33 = phi double [ %12, %14 ], [ %28, %21 ]
%34 = sub nsw i64 0, %16
%35 = icmp eq i64 %18, %34
br i1 %35, label %93, label %73
36: ; preds = %5, %36
%37 = phi i64 [ 0, %5 ], [ %71, %36 ]
%38 = phi double [ 0.000000e+00, %5 ], [ %70, %36 ]
%39 = getelementptr inbounds float, float* %0, i64 %37
%40 = load float, float* %39
%41 = fpext float %40 to double
%42 = getelementptr inbounds float, float* %1, i64 %37
%43 = load float, float* %42
%44 = fpext float %43 to double
%45 = or i64 %37, 1
%46 = getelementptr inbounds float, float* %0, i64 %45
%47 = load float, float* %46
%48 = fpext float %47 to double
%49 = getelementptr inbounds float, float* %1, i64 %45
%50 = load float, float* %49
%51 = fpext float %50 to double
%52 = fmul double %48, %51
%53 = tail call double @llvm.fmuladd.f64(double %41, double %44, double %52)
%54 = or i64 %37, 2
%55 = getelementptr inbounds float, float* %0, i64 %54
%56 = load float, float* %55
%57 = fpext float %56 to double
%58 = getelementptr inbounds float, float* %1, i64 %54
%59 = load float, float* %58
%60 = fpext float %59 to double
%61 = tail call double @llvm.fmuladd.f64(double %57, double %60, double %53)
%62 = or i64 %37, 3
%63 = getelementptr inbounds float, float* %0, i64 %62
%64 = load float, float* %63
%65 = fpext float %64 to double
%66 = getelementptr inbounds float, float* %1, i64 %62
%67 = load float, float* %66
%68 = fpext float %67 to double
%69 = tail call double @llvm.fmuladd.f64(double %65, double %68, double %61)
%70 = fadd double %38, %69
%71 = add nuw nsw i64 %37, 4
%72 = icmp ult i64 %71, %7
br i1 %72, label %36, label %8
73: ; preds = %30, %73
%74 = phi i64 [ %91, %73 ], [ %32, %30 ]
%75 = phi double [ %90, %73 ], [ %33, %30 ]
%76 = getelementptr inbounds float, float* %0, i64 %74
%77 = load float, float* %76
%78 = fpext float %77 to double
%79 = getelementptr inbounds float, float* %1, i64 %74
%80 = load float, float* %79
%81 = fpext float %80 to double
%82 = tail call double @llvm.fmuladd.f64(double %78, double %81, double %75)
%83 = add nuw nsw i64 %74, 1
%84 = getelementptr inbounds float, float* %0, i64 %83
%85 = load float, float* %84
%86 = fpext float %85 to double
%87 = getelementptr inbounds float, float* %1, i64 %83
%88 = load float, float* %87
%89 = fpext float %88 to double
%90 = tail call double @llvm.fmuladd.f64(double %86, double %89, double %82)
%91 = add nuw nsw i64 %74, 2
%92 = icmp eq i64 %91, %16
br i1 %92, label %93, label %73
93: ; preds = %30, %73, %10
%94 = phi double [ %12, %10 ], [ %31, %30 ], [ %90, %73 ]
ret double %94
}