void hamilton_product(double *result, double a1, double b1, double c1,
                      double d1, double a2, double b2, double c2, double d2) {
  result[0] = a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2;
  result[1] = a1 * b2 + b1 * a2 + c1 * d2 - d1 * c2;
  result[2] = a1 * c2 - b1 * d2 + c1 * a2 + d1 * b2;
  result[3] = a1 * d2 + b1 * c2 - c1 * b2 + d1 * a2;
}


x86 assembly (clang, -O0):
<hamilton_product>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  %xmm2,-0x20(%rbp)
movsd  %xmm3,-0x28(%rbp)
movsd  %xmm4,-0x30(%rbp)
movsd  %xmm5,-0x38(%rbp)
movsd  %xmm6,-0x40(%rbp)
movsd  %xmm7,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  -0x30(%rbp),%xmm2
movsd  -0x18(%rbp),%xmm1
mulsd  -0x38(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movsd  -0x40(%rbp),%xmm2
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  -0x28(%rbp),%xmm0
movsd  -0x48(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x10(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x18(%rbp),%xmm1
mulsd  -0x30(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movsd  -0x48(%rbp),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  -0x28(%rbp),%xmm0
movsd  -0x40(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movsd  %xmm0,0x8(%rax)
movsd  -0x10(%rbp),%xmm0
movsd  -0x40(%rbp),%xmm2
movsd  -0x18(%rbp),%xmm1
mulsd  -0x48(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movsd  -0x30(%rbp),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  -0x28(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movsd  %xmm0,0x10(%rax)
movsd  -0x10(%rbp),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x18(%rbp),%xmm1
mulsd  -0x40(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movsd  -0x38(%rbp),%xmm2
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  -0x28(%rbp),%xmm0
movsd  -0x30(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movsd  %xmm0,0x18(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<hamilton_product>:
movapd 0xef7(%rip),%xmm8
movapd %xmm1,%xmm9
xorpd  %xmm8,%xmm9
xorpd  %xmm2,%xmm8
unpcklpd %xmm1,%xmm9
movapd %xmm5,%xmm10
unpcklpd %xmm4,%xmm10
movapd %xmm6,%xmm1
unpcklpd %xmm7,%xmm1
unpcklpd %xmm6,%xmm7
unpcklpd %xmm3,%xmm3
movapd %xmm3,%xmm6
mulpd  %xmm7,%xmm6
mulpd  %xmm9,%xmm7
mulpd  %xmm10,%xmm9
unpcklpd %xmm0,%xmm0
unpcklpd %xmm5,%xmm4
movapd %xmm8,%xmm5
unpcklpd %xmm2,%xmm5
mulpd  %xmm1,%xmm5
mulpd  %xmm0,%xmm1
mulpd  %xmm4,%xmm0
addpd  %xmm9,%xmm0
addpd  %xmm0,%xmm5
subpd  %xmm6,%xmm5
movupd %xmm5,(%rdi)
addpd  %xmm7,%xmm1
unpcklpd %xmm8,%xmm2
mulpd  %xmm4,%xmm2
addpd  %xmm1,%xmm2
mulpd  %xmm10,%xmm3
addpd  %xmm2,%xmm3
movupd %xmm3,0x10(%rdi)
ret

LLVM IR (-O0):
define void @hamilton_product(double* %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8) {
%10 = alloca double*
%11 = alloca double
%12 = alloca double
%13 = alloca double
%14 = alloca double
%15 = alloca double
%16 = alloca double
%17 = alloca double
%18 = alloca double
store double* %0, double** %10
store double %1, double* %11
store double %2, double* %12
store double %3, double* %13
store double %4, double* %14
store double %5, double* %15
store double %6, double* %16
store double %7, double* %17
store double %8, double* %18
%19 = load double, double* %11
%20 = load double, double* %15
%21 = load double, double* %12
%22 = load double, double* %16
%23 = fmul double %21, %22
%24 = fneg double %23
%25 = call double @llvm.fmuladd.f64(double %19, double %20, double %24)
%26 = load double, double* %13
%27 = load double, double* %17
%28 = fneg double %26
%29 = call double @llvm.fmuladd.f64(double %28, double %27, double %25)
%30 = load double, double* %14
%31 = load double, double* %18
%32 = fneg double %30
%33 = call double @llvm.fmuladd.f64(double %32, double %31, double %29)
%34 = load double*, double** %10
%35 = getelementptr inbounds double, double* %34, i64 0
store double %33, double* %35
%36 = load double, double* %11
%37 = load double, double* %16
%38 = load double, double* %12
%39 = load double, double* %15
%40 = fmul double %38, %39
%41 = call double @llvm.fmuladd.f64(double %36, double %37, double %40)
%42 = load double, double* %13
%43 = load double, double* %18
%44 = call double @llvm.fmuladd.f64(double %42, double %43, double %41)
%45 = load double, double* %14
%46 = load double, double* %17
%47 = fneg double %45
%48 = call double @llvm.fmuladd.f64(double %47, double %46, double %44)
%49 = load double*, double** %10
%50 = getelementptr inbounds double, double* %49, i64 1
store double %48, double* %50
%51 = load double, double* %11
%52 = load double, double* %17
%53 = load double, double* %12
%54 = load double, double* %18
%55 = fmul double %53, %54
%56 = fneg double %55
%57 = call double @llvm.fmuladd.f64(double %51, double %52, double %56)
%58 = load double, double* %13
%59 = load double, double* %15
%60 = call double @llvm.fmuladd.f64(double %58, double %59, double %57)
%61 = load double, double* %14
%62 = load double, double* %16
%63 = call double @llvm.fmuladd.f64(double %61, double %62, double %60)
%64 = load double*, double** %10
%65 = getelementptr inbounds double, double* %64, i64 2
store double %63, double* %65
%66 = load double, double* %11
%67 = load double, double* %18
%68 = load double, double* %12
%69 = load double, double* %17
%70 = fmul double %68, %69
%71 = call double @llvm.fmuladd.f64(double %66, double %67, double %70)
%72 = load double, double* %13
%73 = load double, double* %16
%74 = fneg double %72
%75 = call double @llvm.fmuladd.f64(double %74, double %73, double %71)
%76 = load double, double* %14
%77 = load double, double* %15
%78 = call double @llvm.fmuladd.f64(double %76, double %77, double %75)
%79 = load double*, double** %10
%80 = getelementptr inbounds double, double* %79, i64 3
store double %78, double* %80
ret void
}

LLVM IR (-O2):
define void @hamilton_product(double* nocapture writeonly %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8) {
%10 = fneg double %2
%11 = fneg double %3
%12 = fneg double %4
%13 = insertelement <2 x double> poison, double %2, i64 1
%14 = insertelement <2 x double> %13, double %10, i64 0
%15 = insertelement <2 x double> poison, double %6, i64 0
%16 = insertelement <2 x double> %15, double %5, i64 1
%17 = fmul <2 x double> %14, %16
%18 = insertelement <2 x double> poison, double %1, i64 0
%19 = shufflevector <2 x double> %18, <2 x double> poison, <2 x i32> zeroinitializer
%20 = insertelement <2 x double> poison, double %5, i64 0
%21 = insertelement <2 x double> %20, double %6, i64 1
%22 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %19, <2 x double> %21, <2 x double> %17)
%23 = insertelement <2 x double> poison, double %3, i64 1
%24 = insertelement <2 x double> %23, double %11, i64 0
%25 = insertelement <2 x double> poison, double %7, i64 0
%26 = insertelement <2 x double> %25, double %8, i64 1
%27 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %24, <2 x double> %26, <2 x double> %22)
%28 = insertelement <2 x double> poison, double %12, i64 0
%29 = shufflevector <2 x double> %28, <2 x double> poison, <2 x i32> zeroinitializer
%30 = insertelement <2 x double> poison, double %8, i64 0
%31 = insertelement <2 x double> %30, double %7, i64 1
%32 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %29, <2 x double> %31, <2 x double> %27)
%33 = bitcast double* %0 to <2 x double>*
store <2 x double> %32, <2 x double>* %33
%34 = getelementptr inbounds double, double* %0, i64 2
%35 = fmul <2 x double> %14, %31
%36 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %19, <2 x double> %26, <2 x double> %35)
%37 = insertelement <2 x double> poison, double %3, i64 0
%38 = insertelement <2 x double> %37, double %11, i64 1
%39 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %38, <2 x double> %21, <2 x double> %36)
%40 = insertelement <2 x double> poison, double %4, i64 0
%41 = shufflevector <2 x double> %40, <2 x double> poison, <2 x i32> zeroinitializer
%42 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %41, <2 x double> %16, <2 x double> %39)
%43 = bitcast double* %34 to <2 x double>*
store <2 x double> %42, <2 x double>* %43
ret void
}