void vec_dot_prod(_Complex float *x, _Complex float *y, _Complex float *z,
                  int len) {
  int i;
  for (i = 0; i < len; i++) {
    z[i] = x[i] * y[i];
  }
}


x86 assembly (clang, -O0):
<vec_dot_prod>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    1219 <vec_dot_prod+0x119>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movss  (%rax,%rcx,8),%xmm0
movss  %xmm0,-0x48(%rbp)
movss  0x4(%rax,%rcx,8),%xmm2
movss  %xmm2,-0x44(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movss  (%rax,%rcx,8),%xmm4
movss  %xmm4,-0x40(%rbp)
movss  0x4(%rax,%rcx,8),%xmm5
movss  %xmm5,-0x3c(%rbp)
movaps %xmm0,%xmm1
mulss  %xmm4,%xmm1
movaps %xmm2,%xmm3
mulss  %xmm5,%xmm3
mulss  %xmm5,%xmm0
mulss  %xmm4,%xmm2
subss  %xmm3,%xmm1
movss  %xmm1,-0x38(%rbp)
addss  %xmm2,%xmm0
movss  %xmm0,-0x34(%rbp)
ucomiss %xmm1,%xmm1
movss  %xmm1,-0x30(%rbp)
movss  %xmm0,-0x2c(%rbp)
jnp    11ee <vec_dot_prod+0xee>
movss  -0x34(%rbp),%xmm0
movss  -0x38(%rbp),%xmm1
ucomiss %xmm0,%xmm0
movss  %xmm1,-0x30(%rbp)
movss  %xmm0,-0x2c(%rbp)
jnp    11ee <vec_dot_prod+0xee>
movss  -0x3c(%rbp),%xmm3
movss  -0x40(%rbp),%xmm2
movss  -0x44(%rbp),%xmm1
movss  -0x48(%rbp),%xmm0
call   1220 <__mulsc3>
movlpd %xmm0,-0x28(%rbp)
movss  -0x28(%rbp),%xmm1
movss  -0x24(%rbp),%xmm0
movss  %xmm1,-0x30(%rbp)
movss  %xmm0,-0x2c(%rbp)
movss  -0x30(%rbp),%xmm1
movss  -0x2c(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x20(%rbp),%rcx
movss  %xmm1,(%rax,%rcx,8)
movss  %xmm0,0x4(%rax,%rcx,8)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    111e <vec_dot_prod+0x1e>
add    $0x50,%rsp
pop    %rbp
ret
nop

x86 assembly (clang, -O2):
<vec_dot_prod>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
test   %ecx,%ecx
jle    1194 <vec_dot_prod+0x94>
mov    %rdx,%r13
mov    %rsi,%r14
mov    %rdi,%r15
mov    %ecx,%r12d
xor    %ebx,%ebx
nop
movsd  (%r15,%rbx,8),%xmm4
movsd  (%r14,%rbx,8),%xmm2
movaps %xmm4,%xmm0
mulps  %xmm2,%xmm0
movaps %xmm4,%xmm3
shufps $0xe1,%xmm4,%xmm3
mulps  %xmm2,%xmm3
movaps %xmm0,%xmm1
shufps $0x55,%xmm0,%xmm1
subss  %xmm1,%xmm0
movaps %xmm3,%xmm1
shufps $0x55,%xmm3,%xmm1
addss  %xmm3,%xmm1
ucomiss %xmm0,%xmm0
jp     1170 <vec_dot_prod+0x70>
movss  %xmm0,0x0(%r13,%rbx,8)
movss  %xmm1,0x4(%r13,%rbx,8)
add    $0x1,%rbx
cmp    %rbx,%r12
jne    1120 <vec_dot_prod+0x20>
jmp    1194 <vec_dot_prod+0x94>
ucomiss %xmm1,%xmm1
jnp    1157 <vec_dot_prod+0x57>
movaps %xmm4,%xmm1
shufps $0x55,%xmm4,%xmm1
movaps %xmm2,%xmm3
shufps $0x55,%xmm2,%xmm3
movaps %xmm4,%xmm0
call   11a0 <__mulsc3>
movaps %xmm0,%xmm1
shufps $0x55,%xmm0,%xmm1
jmp    1157 <vec_dot_prod+0x57>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret
xchg   %ax,%ax

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

LLVM IR (-O2):
define void @vec_dot_prod({ float, float }* nocapture %0, { float, float }* nocapture %1, { float, float }* nocapture writeonly %2, i32 %3) {
%5 = icmp sgt i32 %3, 0
br i1 %5, label %6, label %43
6: ; preds = %4
%7 = zext i32 %3 to i64
br label %8
8: ; preds = %6, %36
%9 = phi i64 [ 0, %6 ], [ %41, %36 ]
%10 = getelementptr inbounds { float, float }, { float, float }* %0, i64 %9, i32 0
%11 = bitcast float* %10 to <2 x float>*
%12 = load <2 x float>, <2 x float>* %11
%13 = getelementptr inbounds { float, float }, { float, float }* %1, i64 %9, i32 0
%14 = bitcast float* %13 to <2 x float>*
%15 = load <2 x float>, <2 x float>* %14
%16 = fmul <2 x float> %12, %15
%17 = shufflevector <2 x float> %12, <2 x float> poison, <2 x i32> <i32 1, i32 0>
%18 = fmul <2 x float> %17, %15
%19 = shufflevector <2 x float> %16, <2 x float> poison, <2 x i32> <i32 1, i32 undef>
%20 = fsub <2 x float> %16, %19
%21 = extractelement <2 x float> %20, i64 0
%22 = shufflevector <2 x float> %18, <2 x float> poison, <2 x i32> <i32 1, i32 undef>
%23 = fadd <2 x float> %18, %22
%24 = extractelement <2 x float> %23, i64 0
%25 = fcmp uno float %21, 0.000000e+00
br i1 %25, label %26, label %36
26: ; preds = %8
%27 = fcmp uno float %24, 0.000000e+00
br i1 %27, label %28, label %36
28: ; preds = %26
%29 = extractelement <2 x float> %12, i64 0
%30 = extractelement <2 x float> %12, i64 1
%31 = extractelement <2 x float> %15, i64 0
%32 = extractelement <2 x float> %15, i64 1
%33 = tail call <2 x float> @__mulsc3(float %29, float %30, float %31, float %32)
%34 = extractelement <2 x float> %33, i64 0
%35 = extractelement <2 x float> %33, i64 1
br label %36
36: ; preds = %28, %26, %8
%37 = phi float [ %21, %8 ], [ %21, %26 ], [ %34, %28 ]
%38 = phi float [ %24, %8 ], [ %24, %26 ], [ %35, %28 ]
%39 = getelementptr inbounds { float, float }, { float, float }* %2, i64 %9, i32 0
%40 = getelementptr inbounds { float, float }, { float, float }* %2, i64 %9, i32 1
store float %37, float* %39
store float %38, float* %40
%41 = add nuw nsw i64 %9, 1
%42 = icmp eq i64 %41, %7
br i1 %42, label %43, label %8
43: ; preds = %36, %4
ret void
}