#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double fabs(double);
double log(double);
double sqrt(double);
double asinh(double x) {
  int neg = x < 0;
  double z = fabs(x);
  if (z < (1.0 / (1 << (53 / 3))))
    return x;
  if (z < (1.0 / (1 << 53 / 5))) {
    double x2 = z * z;
    z *= 1 + x2 * (-1.0 / 6.0 + x2 * 3.0 / 40.0);
  } else if (z > (1.0 * (1 << 53 / 2))) {
    z = log(z + z);
  } else {
    z = log(z + sqrt(z * z + 1));
  }
  if (neg)
    z = -z;
  return z;
}


x86 assembly (clang, -O0):
<asinh>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
seta   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x14(%rbp)
movsd  -0x10(%rbp),%xmm0
movaps 0xef4(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  0xea3(%rip),%xmm0
ucomisd -0x20(%rbp),%xmm0
jbe    1177 <asinh+0x57>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    128b <asinh+0x16b>
movsd  0xe89(%rip),%xmm0
ucomisd -0x20(%rbp),%xmm0
jbe    11e2 <asinh+0xc2>
movsd  -0x20(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  0xe8a(%rip),%xmm2
mulsd  -0x28(%rbp),%xmm2
movsd  0xe75(%rip),%xmm1
divsd  %xmm1,%xmm2
movsd  0xe61(%rip),%xmm1
addsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  0xe49(%rip),%xmm1
addsd  %xmm1,%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1256 <asinh+0x136>
movsd  -0x20(%rbp),%xmm0
movsd  0xe21(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1212 <asinh+0xf2>
movsd  -0x20(%rbp),%xmm0
addsd  -0x20(%rbp),%xmm0
call   1030 <log@plt>
movsd  %xmm0,-0x20(%rbp)
jmp    1251 <asinh+0x131>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xde6(%rip),%xmm1
addsd  %xmm1,%xmm0
call   1040 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  -0x30(%rbp),%xmm0
addsd  %xmm1,%xmm0
call   1030 <log@plt>
movsd  %xmm0,-0x20(%rbp)
jmp    1256 <asinh+0x136>
cmpl   $0x0,-0x14(%rbp)
je     1281 <asinh+0x161>
movsd  -0x20(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<asinh>:
sub    $0x28,%rsp
movapd %xmm0,%xmm2
movapd 0xed0(%rip),%xmm3
andpd  %xmm0,%xmm3
movsd  0xee4(%rip),%xmm0
ucomisd %xmm3,%xmm0
ja     121c <asinh+0xfc>
movsd  0xeda(%rip),%xmm0
ucomisd %xmm3,%xmm0
jbe    118a <asinh+0x6a>
movapd %xmm2,%xmm0
mulsd  %xmm2,%xmm0
movsd  0xedc(%rip),%xmm1
mulsd  %xmm0,%xmm1
divsd  0xed8(%rip),%xmm1
addsd  0xed8(%rip),%xmm1
mulsd  %xmm0,%xmm1
addsd  0xeb4(%rip),%xmm1
mulsd  %xmm1,%xmm3
jmp    11fb <asinh+0xdb>
ucomisd 0xe9e(%rip),%xmm3
movapd %xmm2,(%rsp)
jbe    11b1 <asinh+0x91>
addsd  %xmm3,%xmm3
movapd %xmm3,%xmm0
call   1030 <log@plt>
movapd (%rsp),%xmm2
movapd %xmm0,%xmm3
jmp    11fb <asinh+0xdb>
mulsd  %xmm2,%xmm2
addsd  0xe7b(%rip),%xmm2
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm2
jb     11d0 <asinh+0xb0>
xorps  %xmm0,%xmm0
sqrtsd %xmm2,%xmm0
jmp    11e5 <asinh+0xc5>
movapd %xmm2,%xmm0
movapd %xmm3,0x10(%rsp)
call   1040 <sqrt@plt>
movapd 0x10(%rsp),%xmm3
addsd  %xmm0,%xmm3
movapd %xmm3,%xmm0
call   1030 <log@plt>
movapd %xmm0,%xmm3
movapd (%rsp),%xmm2
movapd 0xe0d(%rip),%xmm0
xorpd  %xmm3,%xmm0
xorpd  %xmm1,%xmm1
cmpltsd %xmm1,%xmm2
andpd  %xmm2,%xmm0
andnpd %xmm3,%xmm2
orpd   %xmm0,%xmm2
movapd %xmm2,%xmm0
add    $0x28,%rsp
ret

LLVM IR (-O0):
define double @asinh(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca i32
%5 = alloca double
%6 = alloca double
store double %0, double* %3
%7 = load double, double* %3
%8 = fcmp olt double %7, 0.000000e+00
%9 = zext i1 %8 to i32
store i32 %9, i32* %4
%10 = load double, double* %3
%11 = call double @llvm.fabs.f64(double %10)
store double %11, double* %5
%12 = load double, double* %5
%13 = fcmp olt double %12, 0x3EE0000000000000
br i1 %13, label %14, label %16
14: ; preds = %1
%15 = load double, double* %3
store double %15, double* %2
br label %56
16: ; preds = %1
%17 = load double, double* %5
%18 = fcmp olt double %17, 0x3F50000000000000
br i1 %18, label %19, label %31
19: ; preds = %16
%20 = load double, double* %5
%21 = load double, double* %5
%22 = fmul double %20, %21
store double %22, double* %6
%23 = load double, double* %6
%24 = load double, double* %6
%25 = fmul double %24, 3.000000e+00
%26 = fdiv double %25, 4.000000e+01
%27 = fadd double 0xBFC5555555555555, %26
%28 = call double @llvm.fmuladd.f64(double %23, double %27, double 1.000000e+00)
%29 = load double, double* %5
%30 = fmul double %29, %28
store double %30, double* %5
br label %48
31: ; preds = %16
%32 = load double, double* %5
%33 = fcmp ogt double %32, 0x4190000000000000
br i1 %33, label %34, label %39
34: ; preds = %31
%35 = load double, double* %5
%36 = load double, double* %5
%37 = fadd double %35, %36
%38 = call double @log(double %37)
store double %38, double* %5
br label %47
39: ; preds = %31
%40 = load double, double* %5
%41 = load double, double* %5
%42 = load double, double* %5
%43 = call double @llvm.fmuladd.f64(double %41, double %42, double 1.000000e+00)
%44 = call double @sqrt(double %43)
%45 = fadd double %40, %44
%46 = call double @log(double %45)
store double %46, double* %5
br label %47
47: ; preds = %39, %34
br label %48
48: ; preds = %47, %19
%49 = load i32, i32* %4
%50 = icmp ne i32 %49, 0
br i1 %50, label %51, label %54
51: ; preds = %48
%52 = load double, double* %5
%53 = fneg double %52
store double %53, double* %5
br label %54
54: ; preds = %51, %48
%55 = load double, double* %5
store double %55, double* %2
br label %56
56: ; preds = %54, %14
%57 = load double, double* %2
ret double %57
}

LLVM IR (-O2):
define double @asinh(double %0) {
%2 = fcmp olt double %0, 0.000000e+00
%3 = tail call double @llvm.fabs.f64(double %0)
%4 = fcmp olt double %3, 0x3EE0000000000000
br i1 %4, label %28, label %5
5: ; preds = %1
%6 = fcmp olt double %3, 0x3F50000000000000
br i1 %6, label %7, label %14
7: ; preds = %5
%8 = fmul double %0, %0
%9 = fmul double %8, 3.000000e+00
%10 = fdiv double %9, 4.000000e+01
%11 = fadd double %10, 0xBFC5555555555555
%12 = tail call double @llvm.fmuladd.f64(double %8, double %11, double 1.000000e+00)
%13 = fmul double %3, %12
br label %24
14: ; preds = %5
%15 = fcmp ogt double %3, 0x4190000000000000
br i1 %15, label %16, label %19
16: ; preds = %14
%17 = fadd double %3, %3
%18 = tail call double @log(double %17)
br label %24
19: ; preds = %14
%20 = tail call double @llvm.fmuladd.f64(double %0, double %0, double 1.000000e+00)
%21 = tail call double @sqrt(double %20)
%22 = fadd double %3, %21
%23 = tail call double @log(double %22)
br label %24
24: ; preds = %16, %19, %7
%25 = phi double [ %13, %7 ], [ %18, %16 ], [ %23, %19 ]
%26 = fneg double %25
%27 = select i1 %2, double %26, double %25
br label %28
28: ; preds = %1, %24
%29 = phi double [ %27, %24 ], [ %0, %1 ]
ret double %29
}