double fast_InvSqrt(double x) {
  const unsigned long long int R = 0xBFCDD6A18F6A6F55ULL;
  union {
    double f;
    unsigned long long int ul;
  } y;
  y.f = x;
  y.ul = (R - y.ul) >> 1;
  y.f = 0.5 * y.f * (3.0 - x * y.f * y.f);
  y.f = 0.5 * y.f * (3.0 - x * y.f * y.f);
  return y.f;
}


x86 assembly (clang, -O0):
<fast_InvSqrt>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
movabs $0xbfcdd6a18f6a6f55,%rax
d6 cd bf
mov    %rax,-0x10(%rbp)
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movabs $0xbfcdd6a18f6a6f55,%rax
d6 cd bf
sub    -0x18(%rbp),%rax
shr    $0x1,%rax
mov    %rax,-0x18(%rbp)
movsd  0xec9(%rip),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  -0x8(%rbp),%xmm1
mulsd  -0x18(%rbp),%xmm1
movsd  -0x18(%rbp),%xmm2
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm1
movsd  0xe8a(%rip),%xmm2
addsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xe7d(%rip),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  -0x8(%rbp),%xmm1
mulsd  -0x18(%rbp),%xmm1
movsd  -0x18(%rbp),%xmm2
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm1
movsd  0xe3e(%rip),%xmm2
addsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<fast_InvSqrt>:
movq   %xmm0,%rax
movabs $0xbfcdd6a18f6a6f55,%rcx
d6 cd bf
sub    %rax,%rcx
shr    %rcx
movq   %rcx,%xmm1
movsd  0xede(%rip),%xmm2
movdqa %xmm1,%xmm3
mulsd  %xmm0,%xmm3
mulsd  %xmm1,%xmm3
movapd %xmm1,%xmm4
mulsd  %xmm2,%xmm4
movsd  0xeca(%rip),%xmm1
movapd %xmm1,%xmm5
subsd  %xmm3,%xmm5
mulsd  %xmm4,%xmm5
mulsd  %xmm5,%xmm2
mulsd  %xmm5,%xmm0
mulsd  %xmm5,%xmm0
subsd  %xmm0,%xmm1
mulsd  %xmm2,%xmm1
movapd %xmm1,%xmm0
ret

LLVM IR (-O0):
%union.anon = type { double }
define double @fast_InvSqrt(double %0) {
%2 = alloca double
%3 = alloca i64
%4 = alloca %union.anon
store double %0, double* %2
store i64 -4625805252855435435, i64* %3
%5 = load double, double* %2
%6 = bitcast %union.anon* %4 to double*
store double %5, double* %6
%7 = bitcast %union.anon* %4 to i64*
%8 = load i64, i64* %7
%9 = sub i64 -4625805252855435435, %8
%10 = lshr i64 %9, 1
%11 = bitcast %union.anon* %4 to i64*
store i64 %10, i64* %11
%12 = bitcast %union.anon* %4 to double*
%13 = load double, double* %12
%14 = fmul double 5.000000e-01, %13
%15 = load double, double* %2
%16 = bitcast %union.anon* %4 to double*
%17 = load double, double* %16
%18 = fmul double %15, %17
%19 = bitcast %union.anon* %4 to double*
%20 = load double, double* %19
%21 = fneg double %18
%22 = call double @llvm.fmuladd.f64(double %21, double %20, double 3.000000e+00)
%23 = fmul double %14, %22
%24 = bitcast %union.anon* %4 to double*
store double %23, double* %24
%25 = bitcast %union.anon* %4 to double*
%26 = load double, double* %25
%27 = fmul double 5.000000e-01, %26
%28 = load double, double* %2
%29 = bitcast %union.anon* %4 to double*
%30 = load double, double* %29
%31 = fmul double %28, %30
%32 = bitcast %union.anon* %4 to double*
%33 = load double, double* %32
%34 = fneg double %31
%35 = call double @llvm.fmuladd.f64(double %34, double %33, double 3.000000e+00)
%36 = fmul double %27, %35
%37 = bitcast %union.anon* %4 to double*
store double %36, double* %37
%38 = bitcast %union.anon* %4 to double*
%39 = load double, double* %38
ret double %39
}

LLVM IR (-O2):
define double @fast_InvSqrt(double %0) {
%2 = bitcast double %0 to i64
%3 = sub i64 -4625805252855435435, %2
%4 = lshr i64 %3, 1
%5 = bitcast i64 %4 to double
%6 = fmul double %5, 5.000000e-01
%7 = fneg double %5
%8 = fmul double %7, %0
%9 = tail call double @llvm.fmuladd.f64(double %8, double %5, double 3.000000e+00)
%10 = fmul double %6, %9
%11 = fmul double %10, 5.000000e-01
%12 = fneg double %10
%13 = fmul double %12, %0
%14 = tail call double @llvm.fmuladd.f64(double %13, double %10, double 3.000000e+00)
%15 = fmul double %11, %14
ret double %15
}