double acosh(x)
double x;
{
  if (x < 1)
    x = -1;
  else if (x == 1)
    return 0;
  else if (x > (1.0 * (1 << 53 / 2)))
    x += x;
  else
    x += sqrt((x + 1) * (x - 1));
  return log(x);
}


x86 assembly (clang, -O0):
<acosh>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  0xecb(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    1152 <acosh+0x32>
movsd  0xec8(%rip),%xmm0
movsd  %xmm0,-0x10(%rbp)
jmp    11e2 <acosh+0xc2>
movsd  -0x10(%rbp),%xmm0
movsd  0xea1(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    117c <acosh+0x5c>
jp     117c <acosh+0x5c>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11f1 <acosh+0xd1>
movsd  -0x10(%rbp),%xmm0
movsd  0xe7f(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    11a7 <acosh+0x87>
movsd  -0x10(%rbp),%xmm0
addsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
jmp    11d8 <acosh+0xb8>
movsd  0xe51(%rip),%xmm0
addsd  -0x10(%rbp),%xmm0
movsd  -0x10(%rbp),%xmm1
movsd  0xe3f(%rip),%xmm2
subsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
call   1040 <sqrt@plt>
addsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
jmp    11dd <acosh+0xbd>
jmp    11e2 <acosh+0xc2>
movsd  -0x10(%rbp),%xmm0
call   1030 <log@plt>
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<acosh>:
push   %rax
movapd %xmm0,%xmm2
movsd  0xedb(%rip),%xmm0
ucomisd %xmm2,%xmm0
jbe    1141 <acosh+0x21>
movsd  0xec5(%rip),%xmm0
pop    %rax
jmp    1030 <log@plt>
ucomisd 0xebf(%rip),%xmm2
jne    1153 <acosh+0x33>
jp     1153 <acosh+0x33>
xorpd  %xmm0,%xmm0
pop    %rax
ret
ucomisd 0xeb5(%rip),%xmm2
jbe    116b <acosh+0x4b>
addsd  %xmm2,%xmm2
movapd %xmm2,%xmm0
pop    %rax
jmp    1030 <log@plt>
movsd  0xe95(%rip),%xmm1
addsd  %xmm2,%xmm1
movsd  0xe81(%rip),%xmm0
addsd  %xmm2,%xmm0
mulsd  %xmm1,%xmm0
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     1197 <acosh+0x77>
sqrtsd %xmm0,%xmm0
jmp    11a6 <acosh+0x86>
movsd  %xmm2,(%rsp)
call   1040 <sqrt@plt>
movsd  (%rsp),%xmm2
addsd  %xmm2,%xmm0
pop    %rax
jmp    1030 <log@plt>

LLVM IR (-O0):
define double @acosh(double %0) {
%2 = alloca double
%3 = alloca double
store double %0, double* %3
%4 = load double, double* %3
%5 = fcmp olt double %4, 1.000000e+00
br i1 %5, label %6, label %7
6: ; preds = %1
store double -1.000000e+00, double* %3
br label %29
7: ; preds = %1
%8 = load double, double* %3
%9 = fcmp oeq double %8, 1.000000e+00
br i1 %9, label %10, label %11
10: ; preds = %7
store double 0.000000e+00, double* %2
br label %32
11: ; preds = %7
%12 = load double, double* %3
%13 = fcmp ogt double %12, 0x4190000000000000
br i1 %13, label %14, label %18
14: ; preds = %11
%15 = load double, double* %3
%16 = load double, double* %3
%17 = fadd double %16, %15
store double %17, double* %3
br label %27
18: ; preds = %11
%19 = load double, double* %3
%20 = fadd double %19, 1.000000e+00
%21 = load double, double* %3
%22 = fsub double %21, 1.000000e+00
%23 = fmul double %20, %22
%24 = call double @sqrt(double %23)
%25 = load double, double* %3
%26 = fadd double %25, %24
store double %26, double* %3
br label %27
27: ; preds = %18, %14
br label %28
28: ; preds = %27
br label %29
29: ; preds = %28, %6
%30 = load double, double* %3
%31 = call double @log(double %30)
store double %31, double* %2
br label %32
32: ; preds = %29, %10
%33 = load double, double* %2
ret double %33
}

LLVM IR (-O2):
define double @acosh(double %0) {
%2 = fcmp olt double %0, 1.000000e+00
br i1 %2, label %15, label %3
3: ; preds = %1
%4 = fcmp oeq double %0, 1.000000e+00
br i1 %4, label %18, label %5
5: ; preds = %3
%6 = fcmp ogt double %0, 0x4190000000000000
br i1 %6, label %7, label %9
7: ; preds = %5
%8 = fadd double %0, %0
br label %15
9: ; preds = %5
%10 = fadd double %0, 1.000000e+00
%11 = fadd double %0, -1.000000e+00
%12 = fmul double %10, %11
%13 = tail call double @sqrt(double %12)
%14 = fadd double %13, %0
br label %15
15: ; preds = %1, %9, %7
%16 = phi double [ %8, %7 ], [ %14, %9 ], [ -1.000000e+00, %1 ]
%17 = tail call double @log(double %16)
br label %18
18: ; preds = %3, %15
%19 = phi double [ %17, %15 ], [ 0.000000e+00, %3 ]
ret double %19
}