void double_split(double a, double *hi, double *lo) {
  volatile double b, c;
  if (a > 6.69692879491417e+299 || a < -6.69692879491417e+299) {
    a *= 3.7252902984619140625e-09;
    b = 134217729.0 * a;
    c = b - a;
    *hi = b - c;
    *lo = a - *hi;
    *hi *= 268435456.0;
    *lo *= 268435456.0;
  } else {
    b = 134217729.0 * a;
    c = b - a;
    *hi = b - c;
    *lo = a - *hi;
  }
}


x86 assembly (clang, -O0):
<double_split>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
movsd  -0x8(%rbp),%xmm0
movsd  0xee2(%rip),%xmm1
ucomisd %xmm1,%xmm0
ja     113b <double_split+0x3b>
movsd  0xed8(%rip),%xmm0
ucomisd -0x8(%rbp),%xmm0
jbe    11c6 <double_split+0xc6>
movsd  0xedd(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  0xebb(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm1
subsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x8(%rbp),%xmm0
mov    -0x10(%rbp),%rax
subsd  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x10(%rbp),%rax
movsd  0xe73(%rip),%xmm0
mulsd  (%rax),%xmm0
movsd  %xmm0,(%rax)
mov    -0x18(%rbp),%rax
movsd  0xe5f(%rip),%xmm0
mulsd  (%rax),%xmm0
movsd  %xmm0,(%rax)
jmp    1212 <double_split+0x112>
movsd  0xe42(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm1
subsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x8(%rbp),%xmm0
mov    -0x10(%rbp),%rax
subsd  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movsd  %xmm0,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<double_split>:
ucomisd 0xef8(%rip),%xmm0
ja     1153 <double_split+0x53>
movsd  0xef6(%rip),%xmm1
ucomisd %xmm0,%xmm1
ja     1153 <double_split+0x53>
movsd  0xef0(%rip),%xmm1
mulsd  %xmm0,%xmm1
movsd  %xmm1,-0x10(%rsp)
movsd  -0x10(%rsp),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,-0x8(%rsp)
movsd  -0x10(%rsp),%xmm1
subsd  -0x8(%rsp),%xmm1
movsd  %xmm1,(%rdi)
subsd  %xmm1,%xmm0
movsd  %xmm0,(%rsi)
ret
mulsd  0xebd(%rip),%xmm0
movsd  0xead(%rip),%xmm1
mulsd  %xmm0,%xmm1
movsd  %xmm1,-0x10(%rsp)
movsd  -0x10(%rsp),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,-0x8(%rsp)
movsd  -0x10(%rsp),%xmm1
subsd  -0x8(%rsp),%xmm1
movsd  %xmm1,(%rdi)
subsd  %xmm1,%xmm0
movsd  %xmm0,(%rsi)
movsd  0xe83(%rip),%xmm0
movsd  (%rdi),%xmm1
mulsd  %xmm0,%xmm1
movsd  %xmm1,(%rdi)
mulsd  (%rsi),%xmm0
movsd  %xmm0,(%rsi)
ret

LLVM IR (-O0):
define void @double_split(double %0, double* %1, double* %2) {
%4 = alloca double
%5 = alloca double*
%6 = alloca double*
%7 = alloca double
%8 = alloca double
store double %0, double* %4
store double* %1, double** %5
store double* %2, double** %6
%9 = load double, double* %4
%10 = fcmp ogt double %9, 0x7E2FFFFFFFFFFFFF
br i1 %10, label %14, label %11
11: ; preds = %3
%12 = load double, double* %4
%13 = fcmp olt double %12, 0xFE2FFFFFFFFFFFFF
br i1 %13, label %14, label %37
14: ; preds = %11, %3
%15 = load double, double* %4
%16 = fmul double %15, 0x3E30000000000000
store double %16, double* %4
%17 = load double, double* %4
%18 = fmul double 0x41A0000002000000, %17
store volatile double %18, double* %7
%19 = load volatile double, double* %7
%20 = load double, double* %4
%21 = fsub double %19, %20
store volatile double %21, double* %8
%22 = load volatile double, double* %7
%23 = load volatile double, double* %8
%24 = fsub double %22, %23
%25 = load double*, double** %5
store double %24, double* %25
%26 = load double, double* %4
%27 = load double*, double** %5
%28 = load double, double* %27
%29 = fsub double %26, %28
%30 = load double*, double** %6
store double %29, double* %30
%31 = load double*, double** %5
%32 = load double, double* %31
%33 = fmul double %32, 0x41B0000000000000
store double %33, double* %31
%34 = load double*, double** %6
%35 = load double, double* %34
%36 = fmul double %35, 0x41B0000000000000
store double %36, double* %34
br label %52
37: ; preds = %11
%38 = load double, double* %4
%39 = fmul double 0x41A0000002000000, %38
store volatile double %39, double* %7
%40 = load volatile double, double* %7
%41 = load double, double* %4
%42 = fsub double %40, %41
store volatile double %42, double* %8
%43 = load volatile double, double* %7
%44 = load volatile double, double* %8
%45 = fsub double %43, %44
%46 = load double*, double** %5
store double %45, double* %46
%47 = load double, double* %4
%48 = load double*, double** %5
%49 = load double, double* %48
%50 = fsub double %47, %49
%51 = load double*, double** %6
store double %50, double* %51
br label %52
52: ; preds = %37, %14
ret void
}

LLVM IR (-O2):
define void @double_split(double %0, double* nocapture %1, double* nocapture %2) {
%4 = alloca double
%5 = alloca double
%6 = bitcast double* %4 to i8*
%7 = bitcast double* %5 to i8*
%8 = fcmp ogt double %0, 0x7E2FFFFFFFFFFFFF
%9 = fcmp olt double %0, 0xFE2FFFFFFFFFFFFF
%10 = or i1 %8, %9
br i1 %10, label %11, label %24
11: ; preds = %3
%12 = fmul double %0, 0x3E30000000000000
%13 = fmul double %12, 0x41A0000002000000
store volatile double %13, double* %4
%14 = load volatile double, double* %4
%15 = fsub double %14, %12
store volatile double %15, double* %5
%16 = load volatile double, double* %4
%17 = load volatile double, double* %5
%18 = fsub double %16, %17
store double %18, double* %1
%19 = fsub double %12, %18
store double %19, double* %2
%20 = load double, double* %1
%21 = fmul double %20, 0x41B0000000000000
store double %21, double* %1
%22 = load double, double* %2
%23 = fmul double %22, 0x41B0000000000000
br label %32
24: ; preds = %3
%25 = fmul double %0, 0x41A0000002000000
store volatile double %25, double* %4
%26 = load volatile double, double* %4
%27 = fsub double %26, %0
store volatile double %27, double* %5
%28 = load volatile double, double* %4
%29 = load volatile double, double* %5
%30 = fsub double %28, %29
store double %30, double* %1
%31 = fsub double %0, %30
br label %32
32: ; preds = %24, %11
%33 = phi double [ %31, %24 ], [ %23, %11 ]
store double %33, double* %2
ret void
}