void fmac2(long N, double *dst, const float *src1, const float *src2) {
  for (long i = 0; i < N; i++)
    dst[i] += src1[i] * src2[i];
}


x86 assembly (clang, -O0):
<fmac2>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
movq   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x8(%rbp),%rax
jge    116b <fmac2+0x6b>
mov    -0x18(%rbp),%rax
mov    -0x28(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
mov    -0x20(%rbp),%rax
mov    -0x28(%rbp),%rcx
mulss  (%rax,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm0
mov    -0x10(%rbp),%rax
mov    -0x28(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    111c <fmac2+0x1c>
pop    %rbp
ret

x86 assembly (clang, -O2):
<fmac2>:
test   %rdi,%rdi
jle    1195 <fmac2+0x95>
cmp    $0x4,%rdi
jae    1114 <fmac2+0x14>
xor    %r8d,%r8d
jmp    1170 <fmac2+0x70>
mov    %rdi,%r8
and    $0xfffffffffffffffc,%r8
xor    %eax,%eax
nopl   (%rax)
movsd  (%rdx,%rax,4),%xmm0
movsd  0x8(%rdx,%rax,4),%xmm1
movsd  (%rcx,%rax,4),%xmm2
mulps  %xmm0,%xmm2
movsd  0x8(%rcx,%rax,4),%xmm0
mulps  %xmm1,%xmm0
cvtps2pd %xmm2,%xmm1
cvtps2pd %xmm0,%xmm0
movupd (%rsi,%rax,8),%xmm2
addpd  %xmm1,%xmm2
movupd 0x10(%rsi,%rax,8),%xmm1
addpd  %xmm0,%xmm1
movupd %xmm2,(%rsi,%rax,8)
movupd %xmm1,0x10(%rsi,%rax,8)
add    $0x4,%rax
cmp    %rax,%r8
jne    1120 <fmac2+0x20>
cmp    %rdi,%r8
je     1195 <fmac2+0x95>
xchg   %ax,%ax
movss  (%rdx,%r8,4),%xmm0
mulss  (%rcx,%r8,4),%xmm0
cvtss2sd %xmm0,%xmm0
addsd  (%rsi,%r8,8),%xmm0
movsd  %xmm0,(%rsi,%r8,8)
add    $0x1,%r8
cmp    %r8,%rdi
jne    1170 <fmac2+0x70>
ret

LLVM IR (-O0):
define void @fmac2(i64 %0, double* %1, float* %2, float* %3) {
%5 = alloca i64
%6 = alloca double*
%7 = alloca float*
%8 = alloca float*
%9 = alloca i64
store i64 %0, i64* %5
store double* %1, double** %6
store float* %2, float** %7
store float* %3, float** %8
store i64 0, i64* %9
br label %10
10: ; preds = %30, %4
%11 = load i64, i64* %9
%12 = load i64, i64* %5
%13 = icmp slt i64 %11, %12
br i1 %13, label %14, label %33
14: ; preds = %10
%15 = load float*, float** %7
%16 = load i64, i64* %9
%17 = getelementptr inbounds float, float* %15, i64 %16
%18 = load float, float* %17
%19 = load float*, float** %8
%20 = load i64, i64* %9
%21 = getelementptr inbounds float, float* %19, i64 %20
%22 = load float, float* %21
%23 = fmul float %18, %22
%24 = fpext float %23 to double
%25 = load double*, double** %6
%26 = load i64, i64* %9
%27 = getelementptr inbounds double, double* %25, i64 %26
%28 = load double, double* %27
%29 = fadd double %28, %24
store double %29, double* %27
br label %30
30: ; preds = %14
%31 = load i64, i64* %9
%32 = add nsw i64 %31, 1
store i64 %32, i64* %9
br label %10
33: ; preds = %10
ret void
}

LLVM IR (-O2):
define void @fmac2(i64 %0, double* nocapture %1, float* nocapture %2, float* nocapture %3) {
%5 = icmp sgt i64 %0, 0
br i1 %5, label %6, label %44
6: ; preds = %4
%7 = icmp ult i64 %0, 4
br i1 %7, label %42, label %8
8: ; preds = %6
%9 = and i64 %0, -4
br label %10
10: ; preds = %10, %8
%11 = phi i64 [ 0, %8 ], [ %38, %10 ]
%12 = getelementptr inbounds float, float* %2, i64 %11
%13 = bitcast float* %12 to <2 x float>*
%14 = load <2 x float>, <2 x float>* %13
%15 = getelementptr inbounds float, float* %12, i64 2
%16 = bitcast float* %15 to <2 x float>*
%17 = load <2 x float>, <2 x float>* %16
%18 = getelementptr inbounds float, float* %3, i64 %11
%19 = bitcast float* %18 to <2 x float>*
%20 = load <2 x float>, <2 x float>* %19
%21 = getelementptr inbounds float, float* %18, i64 2
%22 = bitcast float* %21 to <2 x float>*
%23 = load <2 x float>, <2 x float>* %22
%24 = fmul <2 x float> %14, %20
%25 = fmul <2 x float> %17, %23
%26 = fpext <2 x float> %24 to <2 x double>
%27 = fpext <2 x float> %25 to <2 x double>
%28 = getelementptr inbounds double, double* %1, i64 %11
%29 = bitcast double* %28 to <2 x double>*
%30 = load <2 x double>, <2 x double>* %29
%31 = getelementptr inbounds double, double* %28, i64 2
%32 = bitcast double* %31 to <2 x double>*
%33 = load <2 x double>, <2 x double>* %32
%34 = fadd <2 x double> %30, %26
%35 = fadd <2 x double> %33, %27
%36 = bitcast double* %28 to <2 x double>*
store <2 x double> %34, <2 x double>* %36
%37 = bitcast double* %31 to <2 x double>*
store <2 x double> %35, <2 x double>* %37
%38 = add nuw i64 %11, 4
%39 = icmp eq i64 %38, %9
br i1 %39, label %40, label %10
40: ; preds = %10
%41 = icmp eq i64 %9, %0
br i1 %41, label %44, label %42
42: ; preds = %6, %40
%43 = phi i64 [ 0, %6 ], [ %9, %40 ]
br label %45
44: ; preds = %45, %40, %4
ret void
45: ; preds = %42, %45
%46 = phi i64 [ %56, %45 ], [ %43, %42 ]
%47 = getelementptr inbounds float, float* %2, i64 %46
%48 = load float, float* %47
%49 = getelementptr inbounds float, float* %3, i64 %46
%50 = load float, float* %49
%51 = fmul float %48, %50
%52 = fpext float %51 to double
%53 = getelementptr inbounds double, double* %1, i64 %46
%54 = load double, double* %53
%55 = fadd double %54, %52
store double %55, double* %53
%56 = add nuw nsw i64 %46, 1
%57 = icmp eq i64 %56, %0
br i1 %57, label %44, label %45
}