void mulpm(float *result, const float *s1, const float *s2) {
  const float x = s1[0] * s2[(0 + (0 << 2))] + s1[1] * s2[(1 + (0 << 2))] +
                  s1[2] * s2[(2 + (0 << 2))] + s2[(3 + (0 << 2))];
  const float y = s1[0] * s2[(0 + (1 << 2))] + s1[1] * s2[(1 + (1 << 2))] +
                  s1[2] * s2[(2 + (1 << 2))] + s2[(3 + (1 << 2))];
  const float z = s1[0] * s2[(0 + (2 << 2))] + s1[1] * s2[(1 + (2 << 2))] +
                  s1[2] * s2[(2 + (2 << 2))] + s2[(3 + (2 << 2))];
  const float w = s1[0] * s2[(0 + (3 << 2))] + s1[1] * s2[(1 + (3 << 2))] +
                  s1[2] * s2[(2 + (3 << 2))] + s2[(3 + (3 << 2))];
  if (w != 1) {
    const double l = 1 / (double)w;
    result[0] = (float)(x * l);
    result[1] = (float)(y * l);
    result[2] = (float)(z * l);
  } else {
    result[0] = x;
    result[1] = y;
    result[2] = z;
  }
}


x86 assembly (clang, -O0):
<mulpm>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm1
mov    -0x18(%rbp),%rax
movss  (%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
mulss  0x4(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  0x8(%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
addss  0xc(%rax),%xmm0
movss  %xmm0,-0x1c(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm1
mov    -0x18(%rbp),%rax
movss  0x10(%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
mulss  0x14(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  0x18(%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
addss  0x1c(%rax),%xmm0
movss  %xmm0,-0x20(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm1
mov    -0x18(%rbp),%rax
movss  0x20(%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
mulss  0x24(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  0x28(%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
addss  0x2c(%rax),%xmm0
movss  %xmm0,-0x24(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm1
mov    -0x18(%rbp),%rax
movss  0x30(%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
mulss  0x34(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  0x38(%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
addss  0x3c(%rax),%xmm0
movss  %xmm0,-0x28(%rbp)
movss  -0x28(%rbp),%xmm0
movss  0xd98(%rip),%xmm1
ucomiss %xmm1,%xmm0
jne    127c <mulpm+0x17c>
jp     127c <mulpm+0x17c>
jmp    12eb <mulpm+0x1eb>
movss  -0x28(%rbp),%xmm0
cvtss2sd %xmm0,%xmm1
movsd  0xd7b(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movss  -0x1c(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
mulsd  -0x30(%rbp),%xmm0
cvtsd2ss %xmm0,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x20(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
mulsd  -0x30(%rbp),%xmm0
cvtsd2ss %xmm0,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0x4(%rax)
movss  -0x24(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
mulsd  -0x30(%rbp),%xmm0
cvtsd2ss %xmm0,%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0x8(%rax)
jmp    1314 <mulpm+0x214>
movss  -0x1c(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x20(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0x4(%rax)
movss  -0x24(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  %xmm0,0x8(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<mulpm>:
movss  (%rsi),%xmm4
movss  0x4(%rsi),%xmm8
movss  0x4(%rdx),%xmm0
mulss  %xmm8,%xmm0
movss  (%rdx),%xmm1
mulss  %xmm4,%xmm1
addss  %xmm0,%xmm1
movss  0x8(%rsi),%xmm3
movss  0x8(%rdx),%xmm9
mulss  %xmm3,%xmm9
addss  %xmm1,%xmm9
addss  0xc(%rdx),%xmm9
movaps %xmm8,%xmm1
shufps $0x0,%xmm8,%xmm1
movss  0x24(%rdx),%xmm5
movss  0x10(%rdx),%xmm6
movss  0x14(%rdx),%xmm7
unpcklps %xmm5,%xmm7
mulps  %xmm1,%xmm7
movss  0x18(%rdx),%xmm5
movss  0x1c(%rdx),%xmm1
movaps %xmm4,%xmm2
shufps $0x0,%xmm4,%xmm2
movss  0x20(%rdx),%xmm0
unpcklps %xmm0,%xmm6
mulps  %xmm2,%xmm6
addps  %xmm7,%xmm6
movaps %xmm3,%xmm0
shufps $0x0,%xmm3,%xmm0
movss  0x28(%rdx),%xmm2
unpcklps %xmm2,%xmm5
mulps  %xmm0,%xmm5
addps  %xmm6,%xmm5
movss  0x2c(%rdx),%xmm0
unpcklps %xmm0,%xmm1
mulss  0x34(%rdx),%xmm8
mulss  0x30(%rdx),%xmm4
mulss  0x38(%rdx),%xmm3
addss  %xmm8,%xmm4
addss  %xmm4,%xmm3
addss  0x3c(%rdx),%xmm3
addps  %xmm5,%xmm1
ucomiss 0xe43(%rip),%xmm3
jne    11c1 <mulpm+0xc1>
jnp    11f9 <mulpm+0xf9>
xorps  %xmm0,%xmm0
cvtss2sd %xmm3,%xmm0
movsd  0xe38(%rip),%xmm2
divsd  %xmm0,%xmm2
xorps  %xmm0,%xmm0
cvtss2sd %xmm9,%xmm0
mulsd  %xmm2,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,(%rdi)
cvtps2pd %xmm1,%xmm0
unpcklpd %xmm2,%xmm2
mulpd  %xmm0,%xmm2
cvtpd2ps %xmm2,%xmm1
jmp    11fe <mulpm+0xfe>
movss  %xmm9,(%rdi)
movss  %xmm1,0x4(%rdi)
shufps $0x55,%xmm1,%xmm1
movss  %xmm1,0x8(%rdi)
ret

LLVM IR (-O0):
define void @mulpm(float* %0, float* %1, float* %2) {
%4 = alloca float*
%5 = alloca float*
%6 = alloca float*
%7 = alloca float
%8 = alloca float
%9 = alloca float
%10 = alloca float
%11 = alloca double
store float* %0, float** %4
store float* %1, float** %5
store float* %2, float** %6
%12 = load float*, float** %5
%13 = getelementptr inbounds float, float* %12, i64 0
%14 = load float, float* %13
%15 = load float*, float** %6
%16 = getelementptr inbounds float, float* %15, i64 0
%17 = load float, float* %16
%18 = load float*, float** %5
%19 = getelementptr inbounds float, float* %18, i64 1
%20 = load float, float* %19
%21 = load float*, float** %6
%22 = getelementptr inbounds float, float* %21, i64 1
%23 = load float, float* %22
%24 = fmul float %20, %23
%25 = call float @llvm.fmuladd.f32(float %14, float %17, float %24)
%26 = load float*, float** %5
%27 = getelementptr inbounds float, float* %26, i64 2
%28 = load float, float* %27
%29 = load float*, float** %6
%30 = getelementptr inbounds float, float* %29, i64 2
%31 = load float, float* %30
%32 = call float @llvm.fmuladd.f32(float %28, float %31, float %25)
%33 = load float*, float** %6
%34 = getelementptr inbounds float, float* %33, i64 3
%35 = load float, float* %34
%36 = fadd float %32, %35
store float %36, float* %7
%37 = load float*, float** %5
%38 = getelementptr inbounds float, float* %37, i64 0
%39 = load float, float* %38
%40 = load float*, float** %6
%41 = getelementptr inbounds float, float* %40, i64 4
%42 = load float, float* %41
%43 = load float*, float** %5
%44 = getelementptr inbounds float, float* %43, i64 1
%45 = load float, float* %44
%46 = load float*, float** %6
%47 = getelementptr inbounds float, float* %46, i64 5
%48 = load float, float* %47
%49 = fmul float %45, %48
%50 = call float @llvm.fmuladd.f32(float %39, float %42, float %49)
%51 = load float*, float** %5
%52 = getelementptr inbounds float, float* %51, i64 2
%53 = load float, float* %52
%54 = load float*, float** %6
%55 = getelementptr inbounds float, float* %54, i64 6
%56 = load float, float* %55
%57 = call float @llvm.fmuladd.f32(float %53, float %56, float %50)
%58 = load float*, float** %6
%59 = getelementptr inbounds float, float* %58, i64 7
%60 = load float, float* %59
%61 = fadd float %57, %60
store float %61, float* %8
%62 = load float*, float** %5
%63 = getelementptr inbounds float, float* %62, i64 0
%64 = load float, float* %63
%65 = load float*, float** %6
%66 = getelementptr inbounds float, float* %65, i64 8
%67 = load float, float* %66
%68 = load float*, float** %5
%69 = getelementptr inbounds float, float* %68, i64 1
%70 = load float, float* %69
%71 = load float*, float** %6
%72 = getelementptr inbounds float, float* %71, i64 9
%73 = load float, float* %72
%74 = fmul float %70, %73
%75 = call float @llvm.fmuladd.f32(float %64, float %67, float %74)
%76 = load float*, float** %5
%77 = getelementptr inbounds float, float* %76, i64 2
%78 = load float, float* %77
%79 = load float*, float** %6
%80 = getelementptr inbounds float, float* %79, i64 10
%81 = load float, float* %80
%82 = call float @llvm.fmuladd.f32(float %78, float %81, float %75)
%83 = load float*, float** %6
%84 = getelementptr inbounds float, float* %83, i64 11
%85 = load float, float* %84
%86 = fadd float %82, %85
store float %86, float* %9
%87 = load float*, float** %5
%88 = getelementptr inbounds float, float* %87, i64 0
%89 = load float, float* %88
%90 = load float*, float** %6
%91 = getelementptr inbounds float, float* %90, i64 12
%92 = load float, float* %91
%93 = load float*, float** %5
%94 = getelementptr inbounds float, float* %93, i64 1
%95 = load float, float* %94
%96 = load float*, float** %6
%97 = getelementptr inbounds float, float* %96, i64 13
%98 = load float, float* %97
%99 = fmul float %95, %98
%100 = call float @llvm.fmuladd.f32(float %89, float %92, float %99)
%101 = load float*, float** %5
%102 = getelementptr inbounds float, float* %101, i64 2
%103 = load float, float* %102
%104 = load float*, float** %6
%105 = getelementptr inbounds float, float* %104, i64 14
%106 = load float, float* %105
%107 = call float @llvm.fmuladd.f32(float %103, float %106, float %100)
%108 = load float*, float** %6
%109 = getelementptr inbounds float, float* %108, i64 15
%110 = load float, float* %109
%111 = fadd float %107, %110
store float %111, float* %10
%112 = load float, float* %10
%113 = fcmp une float %112, 1.000000e+00
br i1 %113, label %114, label %139
114: ; preds = %3
%115 = load float, float* %10
%116 = fpext float %115 to double
%117 = fdiv double 1.000000e+00, %116
store double %117, double* %11
%118 = load float, float* %7
%119 = fpext float %118 to double
%120 = load double, double* %11
%121 = fmul double %119, %120
%122 = fptrunc double %121 to float
%123 = load float*, float** %4
%124 = getelementptr inbounds float, float* %123, i64 0
store float %122, float* %124
%125 = load float, float* %8
%126 = fpext float %125 to double
%127 = load double, double* %11
%128 = fmul double %126, %127
%129 = fptrunc double %128 to float
%130 = load float*, float** %4
%131 = getelementptr inbounds float, float* %130, i64 1
store float %129, float* %131
%132 = load float, float* %9
%133 = fpext float %132 to double
%134 = load double, double* %11
%135 = fmul double %133, %134
%136 = fptrunc double %135 to float
%137 = load float*, float** %4
%138 = getelementptr inbounds float, float* %137, i64 2
store float %136, float* %138
br label %149
139: ; preds = %3
%140 = load float, float* %7
%141 = load float*, float** %4
%142 = getelementptr inbounds float, float* %141, i64 0
store float %140, float* %142
%143 = load float, float* %8
%144 = load float*, float** %4
%145 = getelementptr inbounds float, float* %144, i64 1
store float %143, float* %145
%146 = load float, float* %9
%147 = load float*, float** %4
%148 = getelementptr inbounds float, float* %147, i64 2
store float %146, float* %148
br label %149
149: ; preds = %139, %114
ret void
}

LLVM IR (-O2):
define void @mulpm(float* nocapture writeonly %0, float* nocapture %1, float* nocapture %2) {
%4 = load float, float* %1
%5 = load float, float* %2
%6 = getelementptr inbounds float, float* %1, i64 1
%7 = load float, float* %6
%8 = getelementptr inbounds float, float* %2, i64 1
%9 = load float, float* %8
%10 = fmul float %7, %9
%11 = tail call float @llvm.fmuladd.f32(float %4, float %5, float %10)
%12 = getelementptr inbounds float, float* %1, i64 2
%13 = load float, float* %12
%14 = getelementptr inbounds float, float* %2, i64 2
%15 = load float, float* %14
%16 = tail call float @llvm.fmuladd.f32(float %13, float %15, float %11)
%17 = getelementptr inbounds float, float* %2, i64 3
%18 = load float, float* %17
%19 = fadd float %16, %18
%20 = getelementptr inbounds float, float* %2, i64 4
%21 = load float, float* %20
%22 = getelementptr inbounds float, float* %2, i64 5
%23 = load float, float* %22
%24 = getelementptr inbounds float, float* %2, i64 6
%25 = load float, float* %24
%26 = getelementptr inbounds float, float* %2, i64 7
%27 = load float, float* %26
%28 = getelementptr inbounds float, float* %2, i64 8
%29 = load float, float* %28
%30 = getelementptr inbounds float, float* %2, i64 9
%31 = load float, float* %30
%32 = insertelement <2 x float> poison, float %7, i64 0
%33 = shufflevector <2 x float> %32, <2 x float> poison, <2 x i32> zeroinitializer
%34 = insertelement <2 x float> poison, float %23, i64 0
%35 = insertelement <2 x float> %34, float %31, i64 1
%36 = fmul <2 x float> %33, %35
%37 = insertelement <2 x float> poison, float %4, i64 0
%38 = shufflevector <2 x float> %37, <2 x float> poison, <2 x i32> zeroinitializer
%39 = insertelement <2 x float> poison, float %21, i64 0
%40 = insertelement <2 x float> %39, float %29, i64 1
%41 = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %38, <2 x float> %40, <2 x float> %36)
%42 = getelementptr inbounds float, float* %2, i64 10
%43 = load float, float* %42
%44 = insertelement <2 x float> poison, float %13, i64 0
%45 = shufflevector <2 x float> %44, <2 x float> poison, <2 x i32> zeroinitializer
%46 = insertelement <2 x float> poison, float %25, i64 0
%47 = insertelement <2 x float> %46, float %43, i64 1
%48 = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %45, <2 x float> %47, <2 x float> %41)
%49 = getelementptr inbounds float, float* %2, i64 11
%50 = load float, float* %49
%51 = insertelement <2 x float> poison, float %27, i64 0
%52 = insertelement <2 x float> %51, float %50, i64 1
%53 = fadd <2 x float> %52, %48
%54 = getelementptr inbounds float, float* %2, i64 12
%55 = load float, float* %54
%56 = getelementptr inbounds float, float* %2, i64 13
%57 = load float, float* %56
%58 = fmul float %7, %57
%59 = tail call float @llvm.fmuladd.f32(float %4, float %55, float %58)
%60 = getelementptr inbounds float, float* %2, i64 14
%61 = load float, float* %60
%62 = tail call float @llvm.fmuladd.f32(float %13, float %61, float %59)
%63 = getelementptr inbounds float, float* %2, i64 15
%64 = load float, float* %63
%65 = fadd float %64, %62
%66 = fcmp une float %65, 1.000000e+00
br i1 %66, label %67, label %78
67: ; preds = %3
%68 = fpext float %65 to double
%69 = fdiv double 1.000000e+00, %68
%70 = fpext float %19 to double
%71 = fmul double %69, %70
%72 = fptrunc double %71 to float
store float %72, float* %0
%73 = fpext <2 x float> %53 to <2 x double>
%74 = insertelement <2 x double> poison, double %69, i64 0
%75 = shufflevector <2 x double> %74, <2 x double> poison, <2 x i32> zeroinitializer
%76 = fmul <2 x double> %75, %73
%77 = fptrunc <2 x double> %76 to <2 x float>
br label %79
78: ; preds = %3
store float %19, float* %0
br label %79
79: ; preds = %78, %67
%80 = phi <2 x float> [ %77, %67 ], [ %53, %78 ]
%81 = getelementptr inbounds float, float* %0, i64 1
%82 = extractelement <2 x float> %80, i64 0
store float %82, float* %81
%83 = getelementptr inbounds float, float* %0, i64 2
%84 = extractelement <2 x float> %80, i64 1
store float %84, float* %83
ret void
}