double chi_squared(unsigned long long heads, unsigned long long tails) {
  double sum = 0;
  double tot = heads + tails;
  double expected = 0.5 * tot;
  sum = ((heads - expected) * (heads - expected) / expected) +
        ((tails - expected) * (tails - expected) / expected);
  return sum;
}


x86 assembly (clang, -O0):
<chi_squared>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movq   $0x0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x10(%rbp),%rcx
add    %rcx,%rax
movq   %rax,%xmm0
movaps 0xed5(%rip),%xmm4
punpckldq %xmm4,%xmm0
movapd 0xed9(%rip),%xmm1
subpd  %xmm1,%xmm0
movaps %xmm0,%xmm2
unpckhpd %xmm0,%xmm0
addsd  %xmm2,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  0xec8(%rip),%xmm2
mulsd  %xmm2,%xmm0
movsd  %xmm0,-0x28(%rbp)
movq   -0x8(%rbp),%xmm0
punpckldq %xmm4,%xmm0
subpd  %xmm1,%xmm0
movaps %xmm0,%xmm2
unpckhpd %xmm0,%xmm0
addsd  %xmm2,%xmm0
movsd  -0x28(%rbp),%xmm3
subsd  %xmm3,%xmm0
mulsd  %xmm0,%xmm0
divsd  %xmm3,%xmm0
movq   -0x10(%rbp),%xmm2
punpckldq %xmm4,%xmm2
subpd  %xmm1,%xmm2
movaps %xmm2,%xmm1
unpckhpd %xmm2,%xmm2
addsd  %xmm1,%xmm2
movaps %xmm2,%xmm1
subsd  %xmm3,%xmm1
subsd  -0x28(%rbp),%xmm2
mulsd  %xmm2,%xmm1
divsd  -0x28(%rbp),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<chi_squared>:
lea    (%rsi,%rdi,1),%rax
movq   %rax,%xmm0
punpckldq 0xeef(%rip),%xmm0
subpd  0xef7(%rip),%xmm0
movapd %xmm0,%xmm1
unpckhpd %xmm0,%xmm1
addsd  %xmm0,%xmm1
mulsd  0xf33(%rip),%xmm1
movq   %rsi,%xmm0
movq   %rdi,%xmm2
punpcklqdq %xmm0,%xmm2
movdqa 0xedd(%rip),%xmm0
pand   %xmm2,%xmm0
por    0xee1(%rip),%xmm0
psrlq  $0x20,%xmm2
por    0xee4(%rip),%xmm2
subpd  0xeec(%rip),%xmm2
addpd  %xmm0,%xmm2
unpcklpd %xmm1,%xmm1
subpd  %xmm1,%xmm2
mulpd  %xmm2,%xmm2
divpd  %xmm1,%xmm2
movapd %xmm2,%xmm0
unpckhpd %xmm2,%xmm0
addsd  %xmm2,%xmm0
ret

LLVM IR (-O0):
define double @chi_squared(i64 %0, i64 %1) {
%3 = alloca i64
%4 = alloca i64
%5 = alloca double
%6 = alloca double
%7 = alloca double
store i64 %0, i64* %3
store i64 %1, i64* %4
store double 0.000000e+00, double* %5
%8 = load i64, i64* %3
%9 = load i64, i64* %4
%10 = add i64 %8, %9
%11 = uitofp i64 %10 to double
store double %11, double* %6
%12 = load double, double* %6
%13 = fmul double 5.000000e-01, %12
store double %13, double* %7
%14 = load i64, i64* %3
%15 = uitofp i64 %14 to double
%16 = load double, double* %7
%17 = fsub double %15, %16
%18 = load i64, i64* %3
%19 = uitofp i64 %18 to double
%20 = load double, double* %7
%21 = fsub double %19, %20
%22 = fmul double %17, %21
%23 = load double, double* %7
%24 = fdiv double %22, %23
%25 = load i64, i64* %4
%26 = uitofp i64 %25 to double
%27 = load double, double* %7
%28 = fsub double %26, %27
%29 = load i64, i64* %4
%30 = uitofp i64 %29 to double
%31 = load double, double* %7
%32 = fsub double %30, %31
%33 = fmul double %28, %32
%34 = load double, double* %7
%35 = fdiv double %33, %34
%36 = fadd double %24, %35
store double %36, double* %5
%37 = load double, double* %5
ret double %37
}

LLVM IR (-O2):
define double @chi_squared(i64 %0, i64 %1) {
%3 = add i64 %1, %0
%4 = uitofp i64 %3 to double
%5 = fmul double %4, 5.000000e-01
%6 = insertelement <2 x i64> poison, i64 %0, i64 0
%7 = insertelement <2 x i64> %6, i64 %1, i64 1
%8 = uitofp <2 x i64> %7 to <2 x double>
%9 = insertelement <2 x double> poison, double %5, i64 0
%10 = shufflevector <2 x double> %9, <2 x double> poison, <2 x i32> zeroinitializer
%11 = fsub <2 x double> %8, %10
%12 = fmul <2 x double> %11, %11
%13 = fdiv <2 x double> %12, %10
%14 = shufflevector <2 x double> %13, <2 x double> poison, <2 x i32> <i32 1, i32 undef>
%15 = fadd <2 x double> %13, %14
%16 = extractelement <2 x double> %15, i64 0
ret double %16
}