void m_shadow(const float *plane, const float *light, float *out) {
  float dot;
  dot = plane[0] * light[0] + plane[1] * light[1] + plane[2] * light[2] +
        plane[3] * light[3];
  out[0] = -light[0] * plane[0] + dot;
  out[1] = -light[1] * plane[0];
  out[2] = -light[2] * plane[0];
  out[3] = -light[3] * plane[0];
  out[4] = -light[0] * plane[1];
  out[5] = -light[1] * plane[1] + dot;
  out[6] = -light[2] * plane[1];
  out[7] = -light[3] * plane[1];
  out[8] = -light[0] * plane[2];
  out[9] = -light[1] * plane[2];
  out[10] = -light[2] * plane[2] + dot;
  out[11] = -light[3] * plane[2];
  out[12] = -light[0] * plane[3];
  out[13] = -light[1] * plane[3];
  out[14] = -light[2] * plane[3];
  out[15] = -light[3] * plane[3] + dot;
}


x86 assembly (clang, -O0):
<m_shadow>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm2
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x10(%rbp),%rax
mulss  0x4(%rax),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm1
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm2
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm0
mov    -0x10(%rbp),%rax
movss  0xc(%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x1c(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm2
movss  -0x1c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x4(%rax)
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x8(%rax)
mov    -0x10(%rbp),%rax
movss  0xc(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0xc(%rax)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x10(%rax)
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm2
movss  -0x1c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x14(%rax)
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x18(%rax)
mov    -0x10(%rbp),%rax
movss  0xc(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0x4(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x1c(%rax)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x20(%rax)
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x24(%rax)
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm2
movss  -0x1c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x28(%rax)
mov    -0x10(%rbp),%rax
movss  0xc(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0x8(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x2c(%rax)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0xc(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x30(%rax)
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0xc(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x34(%rax)
mov    -0x10(%rbp),%rax
movss  0x8(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
mulss  0xc(%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x38(%rax)
mov    -0x10(%rbp),%rax
movss  0xc(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm2
movss  -0x1c(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,0x3c(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<m_shadow>:
movss  (%rdi),%xmm1
movss  0x4(%rdi),%xmm0
mulss  0x4(%rsi),%xmm0
mulss  (%rsi),%xmm1
addss  %xmm1,%xmm0
movss  0x8(%rdi),%xmm2
mulss  0x8(%rsi),%xmm2
addss  %xmm0,%xmm2
movss  0xc(%rdi),%xmm0
mulss  0xc(%rsi),%xmm0
addss  %xmm2,%xmm0
movaps %xmm0,%xmm2
subss  %xmm1,%xmm2
movss  %xmm2,(%rdx)
movss  0x4(%rsi),%xmm2
movaps 0xeb7(%rip),%xmm1
xorps  %xmm1,%xmm2
mulss  (%rdi),%xmm2
movss  %xmm2,0x4(%rdx)
movss  0x8(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  (%rdi),%xmm2
movss  %xmm2,0x8(%rdx)
movss  0xc(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  (%rdi),%xmm2
movss  %xmm2,0xc(%rdx)
movss  (%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0x4(%rdi),%xmm2
movss  %xmm2,0x10(%rdx)
movss  0x4(%rsi),%xmm2
mulss  0x4(%rdi),%xmm2
movaps %xmm0,%xmm3
subss  %xmm2,%xmm3
movss  %xmm3,0x14(%rdx)
movss  0x8(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0x4(%rdi),%xmm2
movss  %xmm2,0x18(%rdx)
movss  0xc(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0x4(%rdi),%xmm2
movss  %xmm2,0x1c(%rdx)
movss  (%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0x8(%rdi),%xmm2
movss  %xmm2,0x20(%rdx)
movss  0x4(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0x8(%rdi),%xmm2
movss  %xmm2,0x24(%rdx)
movss  0x8(%rsi),%xmm2
mulss  0x8(%rdi),%xmm2
movaps %xmm0,%xmm3
subss  %xmm2,%xmm3
movss  %xmm3,0x28(%rdx)
movss  0xc(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0x8(%rdi),%xmm2
movss  %xmm2,0x2c(%rdx)
movss  (%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0xc(%rdi),%xmm2
movss  %xmm2,0x30(%rdx)
movss  0x4(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0xc(%rdi),%xmm2
movss  %xmm2,0x34(%rdx)
movss  0x8(%rsi),%xmm2
xorps  %xmm1,%xmm2
mulss  0xc(%rdi),%xmm2
movss  %xmm2,0x38(%rdx)
movss  0xc(%rsi),%xmm1
mulss  0xc(%rdi),%xmm1
subss  %xmm1,%xmm0
movss  %xmm0,0x3c(%rdx)
ret

LLVM IR (-O0):
define void @m_shadow(float* %0, float* %1, float* %2) {
%4 = alloca float*
%5 = alloca float*
%6 = alloca float*
%7 = alloca float
store float* %0, float** %4
store float* %1, float** %5
store float* %2, float** %6
%8 = load float*, float** %4
%9 = getelementptr inbounds float, float* %8, i64 0
%10 = load float, float* %9
%11 = load float*, float** %5
%12 = getelementptr inbounds float, float* %11, i64 0
%13 = load float, float* %12
%14 = load float*, float** %4
%15 = getelementptr inbounds float, float* %14, i64 1
%16 = load float, float* %15
%17 = load float*, float** %5
%18 = getelementptr inbounds float, float* %17, i64 1
%19 = load float, float* %18
%20 = fmul float %16, %19
%21 = call float @llvm.fmuladd.f32(float %10, float %13, float %20)
%22 = load float*, float** %4
%23 = getelementptr inbounds float, float* %22, i64 2
%24 = load float, float* %23
%25 = load float*, float** %5
%26 = getelementptr inbounds float, float* %25, i64 2
%27 = load float, float* %26
%28 = call float @llvm.fmuladd.f32(float %24, float %27, float %21)
%29 = load float*, float** %4
%30 = getelementptr inbounds float, float* %29, i64 3
%31 = load float, float* %30
%32 = load float*, float** %5
%33 = getelementptr inbounds float, float* %32, i64 3
%34 = load float, float* %33
%35 = call float @llvm.fmuladd.f32(float %31, float %34, float %28)
store float %35, float* %7
%36 = load float*, float** %5
%37 = getelementptr inbounds float, float* %36, i64 0
%38 = load float, float* %37
%39 = fneg float %38
%40 = load float*, float** %4
%41 = getelementptr inbounds float, float* %40, i64 0
%42 = load float, float* %41
%43 = load float, float* %7
%44 = call float @llvm.fmuladd.f32(float %39, float %42, float %43)
%45 = load float*, float** %6
%46 = getelementptr inbounds float, float* %45, i64 0
store float %44, float* %46
%47 = load float*, float** %5
%48 = getelementptr inbounds float, float* %47, i64 1
%49 = load float, float* %48
%50 = fneg float %49
%51 = load float*, float** %4
%52 = getelementptr inbounds float, float* %51, i64 0
%53 = load float, float* %52
%54 = fmul float %50, %53
%55 = load float*, float** %6
%56 = getelementptr inbounds float, float* %55, i64 1
store float %54, float* %56
%57 = load float*, float** %5
%58 = getelementptr inbounds float, float* %57, i64 2
%59 = load float, float* %58
%60 = fneg float %59
%61 = load float*, float** %4
%62 = getelementptr inbounds float, float* %61, i64 0
%63 = load float, float* %62
%64 = fmul float %60, %63
%65 = load float*, float** %6
%66 = getelementptr inbounds float, float* %65, i64 2
store float %64, float* %66
%67 = load float*, float** %5
%68 = getelementptr inbounds float, float* %67, i64 3
%69 = load float, float* %68
%70 = fneg float %69
%71 = load float*, float** %4
%72 = getelementptr inbounds float, float* %71, i64 0
%73 = load float, float* %72
%74 = fmul float %70, %73
%75 = load float*, float** %6
%76 = getelementptr inbounds float, float* %75, i64 3
store float %74, float* %76
%77 = load float*, float** %5
%78 = getelementptr inbounds float, float* %77, i64 0
%79 = load float, float* %78
%80 = fneg float %79
%81 = load float*, float** %4
%82 = getelementptr inbounds float, float* %81, i64 1
%83 = load float, float* %82
%84 = fmul float %80, %83
%85 = load float*, float** %6
%86 = getelementptr inbounds float, float* %85, i64 4
store float %84, float* %86
%87 = load float*, float** %5
%88 = getelementptr inbounds float, float* %87, i64 1
%89 = load float, float* %88
%90 = fneg float %89
%91 = load float*, float** %4
%92 = getelementptr inbounds float, float* %91, i64 1
%93 = load float, float* %92
%94 = load float, float* %7
%95 = call float @llvm.fmuladd.f32(float %90, float %93, float %94)
%96 = load float*, float** %6
%97 = getelementptr inbounds float, float* %96, i64 5
store float %95, float* %97
%98 = load float*, float** %5
%99 = getelementptr inbounds float, float* %98, i64 2
%100 = load float, float* %99
%101 = fneg float %100
%102 = load float*, float** %4
%103 = getelementptr inbounds float, float* %102, i64 1
%104 = load float, float* %103
%105 = fmul float %101, %104
%106 = load float*, float** %6
%107 = getelementptr inbounds float, float* %106, i64 6
store float %105, float* %107
%108 = load float*, float** %5
%109 = getelementptr inbounds float, float* %108, i64 3
%110 = load float, float* %109
%111 = fneg float %110
%112 = load float*, float** %4
%113 = getelementptr inbounds float, float* %112, i64 1
%114 = load float, float* %113
%115 = fmul float %111, %114
%116 = load float*, float** %6
%117 = getelementptr inbounds float, float* %116, i64 7
store float %115, float* %117
%118 = load float*, float** %5
%119 = getelementptr inbounds float, float* %118, i64 0
%120 = load float, float* %119
%121 = fneg float %120
%122 = load float*, float** %4
%123 = getelementptr inbounds float, float* %122, i64 2
%124 = load float, float* %123
%125 = fmul float %121, %124
%126 = load float*, float** %6
%127 = getelementptr inbounds float, float* %126, i64 8
store float %125, float* %127
%128 = load float*, float** %5
%129 = getelementptr inbounds float, float* %128, i64 1
%130 = load float, float* %129
%131 = fneg float %130
%132 = load float*, float** %4
%133 = getelementptr inbounds float, float* %132, i64 2
%134 = load float, float* %133
%135 = fmul float %131, %134
%136 = load float*, float** %6
%137 = getelementptr inbounds float, float* %136, i64 9
store float %135, float* %137
%138 = load float*, float** %5
%139 = getelementptr inbounds float, float* %138, i64 2
%140 = load float, float* %139
%141 = fneg float %140
%142 = load float*, float** %4
%143 = getelementptr inbounds float, float* %142, i64 2
%144 = load float, float* %143
%145 = load float, float* %7
%146 = call float @llvm.fmuladd.f32(float %141, float %144, float %145)
%147 = load float*, float** %6
%148 = getelementptr inbounds float, float* %147, i64 10
store float %146, float* %148
%149 = load float*, float** %5
%150 = getelementptr inbounds float, float* %149, i64 3
%151 = load float, float* %150
%152 = fneg float %151
%153 = load float*, float** %4
%154 = getelementptr inbounds float, float* %153, i64 2
%155 = load float, float* %154
%156 = fmul float %152, %155
%157 = load float*, float** %6
%158 = getelementptr inbounds float, float* %157, i64 11
store float %156, float* %158
%159 = load float*, float** %5
%160 = getelementptr inbounds float, float* %159, i64 0
%161 = load float, float* %160
%162 = fneg float %161
%163 = load float*, float** %4
%164 = getelementptr inbounds float, float* %163, i64 3
%165 = load float, float* %164
%166 = fmul float %162, %165
%167 = load float*, float** %6
%168 = getelementptr inbounds float, float* %167, i64 12
store float %166, float* %168
%169 = load float*, float** %5
%170 = getelementptr inbounds float, float* %169, i64 1
%171 = load float, float* %170
%172 = fneg float %171
%173 = load float*, float** %4
%174 = getelementptr inbounds float, float* %173, i64 3
%175 = load float, float* %174
%176 = fmul float %172, %175
%177 = load float*, float** %6
%178 = getelementptr inbounds float, float* %177, i64 13
store float %176, float* %178
%179 = load float*, float** %5
%180 = getelementptr inbounds float, float* %179, i64 2
%181 = load float, float* %180
%182 = fneg float %181
%183 = load float*, float** %4
%184 = getelementptr inbounds float, float* %183, i64 3
%185 = load float, float* %184
%186 = fmul float %182, %185
%187 = load float*, float** %6
%188 = getelementptr inbounds float, float* %187, i64 14
store float %186, float* %188
%189 = load float*, float** %5
%190 = getelementptr inbounds float, float* %189, i64 3
%191 = load float, float* %190
%192 = fneg float %191
%193 = load float*, float** %4
%194 = getelementptr inbounds float, float* %193, i64 3
%195 = load float, float* %194
%196 = load float, float* %7
%197 = call float @llvm.fmuladd.f32(float %192, float %195, float %196)
%198 = load float*, float** %6
%199 = getelementptr inbounds float, float* %198, i64 15
store float %197, float* %199
ret void
}

LLVM IR (-O2):
define void @m_shadow(float* nocapture %0, float* nocapture %1, float* nocapture writeonly %2) {
%4 = load float, float* %0
%5 = load float, float* %1
%6 = getelementptr inbounds float, float* %0, i64 1
%7 = load float, float* %6
%8 = getelementptr inbounds float, float* %1, 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* %0, i64 2
%13 = load float, float* %12
%14 = getelementptr inbounds float, float* %1, 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* %0, i64 3
%18 = load float, float* %17
%19 = getelementptr inbounds float, float* %1, i64 3
%20 = load float, float* %19
%21 = tail call float @llvm.fmuladd.f32(float %18, float %20, float %16)
%22 = fneg float %5
%23 = tail call float @llvm.fmuladd.f32(float %22, float %4, float %21)
store float %23, float* %2
%24 = load float, float* %8
%25 = fneg float %24
%26 = load float, float* %0
%27 = fmul float %26, %25
%28 = getelementptr inbounds float, float* %2, i64 1
store float %27, float* %28
%29 = load float, float* %14
%30 = fneg float %29
%31 = load float, float* %0
%32 = fmul float %31, %30
%33 = getelementptr inbounds float, float* %2, i64 2
store float %32, float* %33
%34 = load float, float* %19
%35 = fneg float %34
%36 = load float, float* %0
%37 = fmul float %36, %35
%38 = getelementptr inbounds float, float* %2, i64 3
store float %37, float* %38
%39 = load float, float* %1
%40 = fneg float %39
%41 = load float, float* %6
%42 = fmul float %41, %40
%43 = getelementptr inbounds float, float* %2, i64 4
store float %42, float* %43
%44 = load float, float* %8
%45 = fneg float %44
%46 = load float, float* %6
%47 = tail call float @llvm.fmuladd.f32(float %45, float %46, float %21)
%48 = getelementptr inbounds float, float* %2, i64 5
store float %47, float* %48
%49 = load float, float* %14
%50 = fneg float %49
%51 = load float, float* %6
%52 = fmul float %51, %50
%53 = getelementptr inbounds float, float* %2, i64 6
store float %52, float* %53
%54 = load float, float* %19
%55 = fneg float %54
%56 = load float, float* %6
%57 = fmul float %56, %55
%58 = getelementptr inbounds float, float* %2, i64 7
store float %57, float* %58
%59 = load float, float* %1
%60 = fneg float %59
%61 = load float, float* %12
%62 = fmul float %61, %60
%63 = getelementptr inbounds float, float* %2, i64 8
store float %62, float* %63
%64 = load float, float* %8
%65 = fneg float %64
%66 = load float, float* %12
%67 = fmul float %66, %65
%68 = getelementptr inbounds float, float* %2, i64 9
store float %67, float* %68
%69 = load float, float* %14
%70 = fneg float %69
%71 = load float, float* %12
%72 = tail call float @llvm.fmuladd.f32(float %70, float %71, float %21)
%73 = getelementptr inbounds float, float* %2, i64 10
store float %72, float* %73
%74 = load float, float* %19
%75 = fneg float %74
%76 = load float, float* %12
%77 = fmul float %76, %75
%78 = getelementptr inbounds float, float* %2, i64 11
store float %77, float* %78
%79 = load float, float* %1
%80 = fneg float %79
%81 = load float, float* %17
%82 = fmul float %81, %80
%83 = getelementptr inbounds float, float* %2, i64 12
store float %82, float* %83
%84 = load float, float* %8
%85 = fneg float %84
%86 = load float, float* %17
%87 = fmul float %86, %85
%88 = getelementptr inbounds float, float* %2, i64 13
store float %87, float* %88
%89 = load float, float* %14
%90 = fneg float %89
%91 = load float, float* %17
%92 = fmul float %91, %90
%93 = getelementptr inbounds float, float* %2, i64 14
store float %92, float* %93
%94 = load float, float* %19
%95 = fneg float %94
%96 = load float, float* %17
%97 = tail call float @llvm.fmuladd.f32(float %95, float %96, float %21)
%98 = getelementptr inbounds float, float* %2, i64 15
store float %97, float* %98
ret void
}