void vtVma(float *vec1, float *vec2, float *vec3, int N) {
  for (int k = 0; k < N; k++) {
    vec3[k] += vec1[k] * vec2[k];
  }
}


x86 assembly (clang, -O0):
<vtVma>:
push   %rbp
mov    %rsp,%rbp
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    1168 <vtVma+0x68>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm2
mov    -0x18(%rbp),%rax
movslq -0x20(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,(%rax,%rcx,4)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    111a <vtVma+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<vtVma>:
test   %ecx,%ecx
jle    128d <vtVma+0x18d>
mov    %ecx,%r8d
cmp    $0x8,%ecx
jae    117a <vtVma+0x7a>
xor    %ecx,%ecx
mov    %rcx,%rax
not    %rax
test   $0x1,%r8b
je     1136 <vtVma+0x36>
movss  (%rdi,%rcx,4),%xmm0
mulss  (%rsi,%rcx,4),%xmm0
addss  (%rdx,%rcx,4),%xmm0
movss  %xmm0,(%rdx,%rcx,4)
or     $0x1,%rcx
add    %r8,%rax
je     128d <vtVma+0x18d>
nop
movss  (%rdi,%rcx,4),%xmm0
mulss  (%rsi,%rcx,4),%xmm0
addss  (%rdx,%rcx,4),%xmm0
movss  %xmm0,(%rdx,%rcx,4)
movss  0x4(%rdi,%rcx,4),%xmm0
mulss  0x4(%rsi,%rcx,4),%xmm0
addss  0x4(%rdx,%rcx,4),%xmm0
movss  %xmm0,0x4(%rdx,%rcx,4)
add    $0x2,%rcx
cmp    %rcx,%r8
jne    1140 <vtVma+0x40>
jmp    128d <vtVma+0x18d>
lea    (%rdx,%r8,4),%rcx
lea    (%rdi,%r8,4),%rax
cmp    %rdx,%rax
seta   %r10b
lea    (%rsi,%r8,4),%rax
cmp    %rdi,%rcx
seta   %r11b
cmp    %rdx,%rax
seta   %al
cmp    %rsi,%rcx
seta   %r9b
xor    %ecx,%ecx
test   %r11b,%r10b
jne    1112 <vtVma+0x12>
and    %r9b,%al
jne    1112 <vtVma+0x12>
mov    %r8d,%ecx
and    $0xfffffff8,%ecx
lea    -0x8(%rcx),%rax
mov    %rax,%r9
shr    $0x3,%r9
add    $0x1,%r9
test   %rax,%rax
je     128e <vtVma+0x18e>
mov    %r9,%r10
and    $0xfffffffffffffffe,%r10
xor    %eax,%eax
nopl   0x0(%rax)
movups (%rdi,%rax,4),%xmm0
movups 0x10(%rdi,%rax,4),%xmm1
movups (%rsi,%rax,4),%xmm2
mulps  %xmm0,%xmm2
movups 0x10(%rsi,%rax,4),%xmm0
mulps  %xmm1,%xmm0
movups (%rdx,%rax,4),%xmm1
addps  %xmm2,%xmm1
movups 0x10(%rdx,%rax,4),%xmm2
addps  %xmm0,%xmm2
movups 0x20(%rdx,%rax,4),%xmm0
movups 0x30(%rdx,%rax,4),%xmm3
movups %xmm1,(%rdx,%rax,4)
movups %xmm2,0x10(%rdx,%rax,4)
movups 0x20(%rdi,%rax,4),%xmm1
movups 0x30(%rdi,%rax,4),%xmm2
movups 0x20(%rsi,%rax,4),%xmm4
mulps  %xmm1,%xmm4
addps  %xmm0,%xmm4
movups 0x30(%rsi,%rax,4),%xmm0
mulps  %xmm2,%xmm0
addps  %xmm3,%xmm0
movups %xmm4,0x20(%rdx,%rax,4)
movups %xmm0,0x30(%rdx,%rax,4)
add    $0x10,%rax
add    $0xfffffffffffffffe,%r10
jne    11e0 <vtVma+0xe0>
test   $0x1,%r9b
je     1284 <vtVma+0x184>
movups (%rdi,%rax,4),%xmm0
movups 0x10(%rdi,%rax,4),%xmm1
movups (%rsi,%rax,4),%xmm2
mulps  %xmm0,%xmm2
movups 0x10(%rsi,%rax,4),%xmm0
mulps  %xmm1,%xmm0
movups (%rdx,%rax,4),%xmm1
addps  %xmm2,%xmm1
movups 0x10(%rdx,%rax,4),%xmm2
addps  %xmm0,%xmm2
movups %xmm1,(%rdx,%rax,4)
movups %xmm2,0x10(%rdx,%rax,4)
cmp    %r8,%rcx
jne    1112 <vtVma+0x12>
ret
xor    %eax,%eax
test   $0x1,%r9b
jne    1254 <vtVma+0x154>
jmp    1284 <vtVma+0x184>

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

LLVM IR (-O2):
define void @vtVma(float* nocapture %0, float* nocapture %1, float* nocapture %2, i32 %3) {
%5 = icmp sgt i32 %3, 0
br i1 %5, label %6, label %126
6: ; preds = %4
%7 = zext i32 %3 to i64
%8 = icmp ult i32 %3, 8
br i1 %8, label %108, label %9
9: ; preds = %6
%10 = getelementptr float, float* %2, i64 %7
%11 = getelementptr float, float* %0, i64 %7
%12 = getelementptr float, float* %1, i64 %7
%13 = icmp ugt float* %11, %2
%14 = icmp ugt float* %10, %0
%15 = and i1 %13, %14
%16 = icmp ugt float* %12, %2
%17 = icmp ugt float* %10, %1
%18 = and i1 %16, %17
%19 = or i1 %15, %18
br i1 %19, label %108, label %20
20: ; preds = %9
%21 = and i64 %7, 4294967288
%22 = add nsw i64 %21, -8
%23 = lshr exact i64 %22, 3
%24 = add nuw nsw i64 %23, 1
%25 = and i64 %24, 1
%26 = icmp eq i64 %22, 0
br i1 %26, label %80, label %27
27: ; preds = %20
%28 = and i64 %24, 4611686018427387902
br label %29
29: ; preds = %29, %27
%30 = phi i64 [ 0, %27 ], [ %77, %29 ]
%31 = phi i64 [ 0, %27 ], [ %78, %29 ]
%32 = getelementptr inbounds float, float* %0, i64 %30
%33 = bitcast float* %32 to <4 x float>*
%34 = load <4 x float>, <4 x float>* %33
%35 = getelementptr inbounds float, float* %32, i64 4
%36 = bitcast float* %35 to <4 x float>*
%37 = load <4 x float>, <4 x float>* %36
%38 = getelementptr inbounds float, float* %1, i64 %30
%39 = bitcast float* %38 to <4 x float>*
%40 = load <4 x float>, <4 x float>* %39
%41 = getelementptr inbounds float, float* %38, i64 4
%42 = bitcast float* %41 to <4 x float>*
%43 = load <4 x float>, <4 x float>* %42
%44 = getelementptr inbounds float, float* %2, i64 %30
%45 = bitcast float* %44 to <4 x float>*
%46 = load <4 x float>, <4 x float>* %45
%47 = getelementptr inbounds float, float* %44, i64 4
%48 = bitcast float* %47 to <4 x float>*
%49 = load <4 x float>, <4 x float>* %48
%50 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %34, <4 x float> %40, <4 x float> %46)
%51 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %37, <4 x float> %43, <4 x float> %49)
%52 = bitcast float* %44 to <4 x float>*
store <4 x float> %50, <4 x float>* %52
%53 = bitcast float* %47 to <4 x float>*
store <4 x float> %51, <4 x float>* %53
%54 = or i64 %30, 8
%55 = getelementptr inbounds float, float* %0, i64 %54
%56 = bitcast float* %55 to <4 x float>*
%57 = load <4 x float>, <4 x float>* %56
%58 = getelementptr inbounds float, float* %55, i64 4
%59 = bitcast float* %58 to <4 x float>*
%60 = load <4 x float>, <4 x float>* %59
%61 = getelementptr inbounds float, float* %1, i64 %54
%62 = bitcast float* %61 to <4 x float>*
%63 = load <4 x float>, <4 x float>* %62
%64 = getelementptr inbounds float, float* %61, i64 4
%65 = bitcast float* %64 to <4 x float>*
%66 = load <4 x float>, <4 x float>* %65
%67 = getelementptr inbounds float, float* %2, i64 %54
%68 = bitcast float* %67 to <4 x float>*
%69 = load <4 x float>, <4 x float>* %68
%70 = getelementptr inbounds float, float* %67, i64 4
%71 = bitcast float* %70 to <4 x float>*
%72 = load <4 x float>, <4 x float>* %71
%73 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %57, <4 x float> %63, <4 x float> %69)
%74 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %60, <4 x float> %66, <4 x float> %72)
%75 = bitcast float* %67 to <4 x float>*
store <4 x float> %73, <4 x float>* %75
%76 = bitcast float* %70 to <4 x float>*
store <4 x float> %74, <4 x float>* %76
%77 = add nuw i64 %30, 16
%78 = add i64 %31, 2
%79 = icmp eq i64 %78, %28
br i1 %79, label %80, label %29
80: ; preds = %29, %20
%81 = phi i64 [ 0, %20 ], [ %77, %29 ]
%82 = icmp eq i64 %25, 0
br i1 %82, label %106, label %83
83: ; preds = %80
%84 = getelementptr inbounds float, float* %0, i64 %81
%85 = bitcast float* %84 to <4 x float>*
%86 = load <4 x float>, <4 x float>* %85
%87 = getelementptr inbounds float, float* %84, i64 4
%88 = bitcast float* %87 to <4 x float>*
%89 = load <4 x float>, <4 x float>* %88
%90 = getelementptr inbounds float, float* %1, i64 %81
%91 = bitcast float* %90 to <4 x float>*
%92 = load <4 x float>, <4 x float>* %91
%93 = getelementptr inbounds float, float* %90, i64 4
%94 = bitcast float* %93 to <4 x float>*
%95 = load <4 x float>, <4 x float>* %94
%96 = getelementptr inbounds float, float* %2, i64 %81
%97 = bitcast float* %96 to <4 x float>*
%98 = load <4 x float>, <4 x float>* %97
%99 = getelementptr inbounds float, float* %96, i64 4
%100 = bitcast float* %99 to <4 x float>*
%101 = load <4 x float>, <4 x float>* %100
%102 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %86, <4 x float> %92, <4 x float> %98)
%103 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %89, <4 x float> %95, <4 x float> %101)
%104 = bitcast float* %96 to <4 x float>*
store <4 x float> %102, <4 x float>* %104
%105 = bitcast float* %99 to <4 x float>*
store <4 x float> %103, <4 x float>* %105
br label %106
106: ; preds = %80, %83
%107 = icmp eq i64 %21, %7
br i1 %107, label %126, label %108
108: ; preds = %9, %6, %106
%109 = phi i64 [ 0, %9 ], [ 0, %6 ], [ %21, %106 ]
%110 = xor i64 %109, -1
%111 = and i64 %7, 1
%112 = icmp eq i64 %111, 0
br i1 %112, label %122, label %113
113: ; preds = %108
%114 = getelementptr inbounds float, float* %0, i64 %109
%115 = load float, float* %114
%116 = getelementptr inbounds float, float* %1, i64 %109
%117 = load float, float* %116
%118 = getelementptr inbounds float, float* %2, i64 %109
%119 = load float, float* %118
%120 = tail call float @llvm.fmuladd.f32(float %115, float %117, float %119)
store float %120, float* %118
%121 = or i64 %109, 1
br label %122
122: ; preds = %113, %108
%123 = phi i64 [ %109, %108 ], [ %121, %113 ]
%124 = sub nsw i64 0, %7
%125 = icmp eq i64 %110, %124
br i1 %125, label %126, label %127
126: ; preds = %122, %127, %106, %4
ret void
127: ; preds = %122, %127
%128 = phi i64 [ %144, %127 ], [ %123, %122 ]
%129 = getelementptr inbounds float, float* %0, i64 %128
%130 = load float, float* %129
%131 = getelementptr inbounds float, float* %1, i64 %128
%132 = load float, float* %131
%133 = getelementptr inbounds float, float* %2, i64 %128
%134 = load float, float* %133
%135 = tail call float @llvm.fmuladd.f32(float %130, float %132, float %134)
store float %135, float* %133
%136 = add nuw nsw i64 %128, 1
%137 = getelementptr inbounds float, float* %0, i64 %136
%138 = load float, float* %137
%139 = getelementptr inbounds float, float* %1, i64 %136
%140 = load float, float* %139
%141 = getelementptr inbounds float, float* %2, i64 %136
%142 = load float, float* %141
%143 = tail call float @llvm.fmuladd.f32(float %138, float %140, float %142)
store float %143, float* %141
%144 = add nuw nsw i64 %128, 2
%145 = icmp eq i64 %144, %7
br i1 %145, label %126, label %127
}