#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 expm1(double);
double fabs(double);
double tanh(double x) {
  double t, z;
  int jx, ix;
  jx = *(1 + (const int *)&x);
  ix = jx & 0x7fffffff;
  if (ix >= 0x7ff00000) {
    if (jx >= 0) {
      return 1.0 / x + 1.0;
    } else {
      return 1.0 / x - 1.0;
    }
  }
  if (ix < 0x40360000) {
    if (ix < 0x3c800000) {
      return x * (1.0 + x);
    }
    if (ix >= 0x3ff00000) {
      t = expm1(2.0 * fabs(x));
      z = 1.0 - 2.0 / (t + 2.0);
    } else {
      t = expm1(-2.0 * fabs(x));
      z = -t / (t + 2.0);
    }
  } else {
    z = 1.0 - 1.0e-300;
  }
  return (jx >= 0) ? z : -z;
}


x86 assembly (clang, -O0):
<tanh>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
mov    -0xc(%rbp),%eax
mov    %eax,-0x24(%rbp)
mov    -0x24(%rbp),%eax
and    $0x7fffffff,%eax
mov    %eax,-0x28(%rbp)
cmpl   $0x7ff00000,-0x28(%rbp)
jl     118b <tanh+0x7b>
cmpl   $0x0,-0x24(%rbp)
jl     1168 <tanh+0x58>
movsd  0xeb3(%rip),%xmm0
divsd  -0x10(%rbp),%xmm0
movsd  0xea6(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    12d5 <tanh+0x1c5>
movsd  0xe90(%rip),%xmm0
divsd  -0x10(%rbp),%xmm0
movsd  0xe83(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    12d5 <tanh+0x1c5>
cmpl   $0x40360000,-0x28(%rbp)
jge    1284 <tanh+0x174>
cmpl   $0x3c800000,-0x28(%rbp)
jge    11c5 <tanh+0xb5>
movsd  -0x10(%rbp),%xmm0
movsd  0xe4e(%rip),%xmm1
addsd  -0x10(%rbp),%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    12d5 <tanh+0x1c5>
cmpl   $0x3ff00000,-0x28(%rbp)
jl     1227 <tanh+0x117>
movsd  -0x10(%rbp),%xmm1
movaps 0xe42(%rip),%xmm0
pand   %xmm0,%xmm1
movsd  0xe1e(%rip),%xmm0
mulsd  %xmm1,%xmm0
call   1030 <expm1@plt>
movsd  %xmm0,-0x18(%rbp)
movsd  0xe08(%rip),%xmm0
addsd  -0x18(%rbp),%xmm0
movsd  0xdfb(%rip),%xmm1
divsd  %xmm0,%xmm1
movsd  0xde7(%rip),%xmm0
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    127f <tanh+0x16f>
movsd  -0x10(%rbp),%xmm1
movaps 0xded(%rip),%xmm0
pand   %xmm0,%xmm1
movsd  0xdd1(%rip),%xmm0
mulsd  %xmm1,%xmm0
call   1030 <expm1@plt>
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  0xd97(%rip),%xmm1
addsd  -0x18(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1291 <tanh+0x181>
movsd  0xd74(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
cmpl   $0x0,-0x24(%rbp)
jl     12aa <tanh+0x19a>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
jmp    12cb <tanh+0x1bb>
movsd  -0x20(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<tanh>:
push   %rbx
movdqa %xmm0,%xmm1
movq   %xmm0,%rbx
mov    %rbx,%rax
shr    $0x20,%rax
and    $0x7fffffff,%eax
cmp    $0x7ff00000,%eax
jb     1148 <tanh+0x38>
movsd  0xecb(%rip),%xmm0
divsd  %xmm1,%xmm0
test   %rbx,%rbx
js     117e <tanh+0x6e>
addsd  0xeba(%rip),%xmm0
pop    %rbx
ret
cmp    $0x4035ffff,%eax
ja     1168 <tanh+0x58>
cmp    $0x3c7fffff,%eax
ja     1188 <tanh+0x78>
movsd  0xea2(%rip),%xmm0
addsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
pop    %rbx
ret
movsd  0xe90(%rip),%xmm0
test   %rbx,%rbx
js     11f9 <tanh+0xe9>
jmp    1201 <tanh+0xf1>
addsd  0xe92(%rip),%xmm0
pop    %rbx
ret
pand   0xe90(%rip),%xmm1
cmp    $0x3ff00000,%eax
jb     11c7 <tanh+0xb7>
addsd  %xmm1,%xmm1
movapd %xmm1,%xmm0
call   1030 <expm1@plt>
movsd  0xe64(%rip),%xmm1
addsd  %xmm1,%xmm0
divsd  %xmm0,%xmm1
movsd  0xe44(%rip),%xmm0
subsd  %xmm1,%xmm0
test   %rbx,%rbx
js     11f9 <tanh+0xe9>
jmp    1201 <tanh+0xf1>
mulsd  0xe39(%rip),%xmm1
movapd %xmm1,%xmm0
call   1030 <expm1@plt>
movapd %xmm0,%xmm1
movapd 0xe4c(%rip),%xmm0
xorpd  %xmm1,%xmm0
addsd  0xe20(%rip),%xmm1
divsd  %xmm1,%xmm0
test   %rbx,%rbx
jns    1201 <tanh+0xf1>
xorpd  0xe2f(%rip),%xmm0
pop    %rbx
ret

LLVM IR (-O0):
define double @tanh(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca i32
%7 = alloca i32
store double %0, double* %3
%8 = bitcast double* %3 to i32*
%9 = getelementptr inbounds i32, i32* %8, i64 1
%10 = load i32, i32* %9
store i32 %10, i32* %6
%11 = load i32, i32* %6
%12 = and i32 %11, 2147483647
store i32 %12, i32* %7
%13 = load i32, i32* %7
%14 = icmp sge i32 %13, 2146435072
br i1 %14, label %15, label %26
15: ; preds = %1
%16 = load i32, i32* %6
%17 = icmp sge i32 %16, 0
br i1 %17, label %18, label %22
18: ; preds = %15
%19 = load double, double* %3
%20 = fdiv double 1.000000e+00, %19
%21 = fadd double %20, 1.000000e+00
store double %21, double* %2
br label %71
22: ; preds = %15
%23 = load double, double* %3
%24 = fdiv double 1.000000e+00, %23
%25 = fsub double %24, 1.000000e+00
store double %25, double* %2
br label %71
26: ; preds = %1
%27 = load i32, i32* %7
%28 = icmp slt i32 %27, 1077280768
br i1 %28, label %29, label %60
29: ; preds = %26
%30 = load i32, i32* %7
%31 = icmp slt i32 %30, 1015021568
br i1 %31, label %32, label %37
32: ; preds = %29
%33 = load double, double* %3
%34 = load double, double* %3
%35 = fadd double 1.000000e+00, %34
%36 = fmul double %33, %35
store double %36, double* %2
br label %71
37: ; preds = %29
%38 = load i32, i32* %7
%39 = icmp sge i32 %38, 1072693248
br i1 %39, label %40, label %49
40: ; preds = %37
%41 = load double, double* %3
%42 = call double @llvm.fabs.f64(double %41)
%43 = fmul double 2.000000e+00, %42
%44 = call double @expm1(double %43)
store double %44, double* %4
%45 = load double, double* %4
%46 = fadd double %45, 2.000000e+00
%47 = fdiv double 2.000000e+00, %46
%48 = fsub double 1.000000e+00, %47
store double %48, double* %5
br label %59
49: ; preds = %37
%50 = load double, double* %3
%51 = call double @llvm.fabs.f64(double %50)
%52 = fmul double -2.000000e+00, %51
%53 = call double @expm1(double %52)
store double %53, double* %4
%54 = load double, double* %4
%55 = fneg double %54
%56 = load double, double* %4
%57 = fadd double %56, 2.000000e+00
%58 = fdiv double %55, %57
store double %58, double* %5
br label %59
59: ; preds = %49, %40
br label %61
60: ; preds = %26
store double 1.000000e+00, double* %5
br label %61
61: ; preds = %60, %59
%62 = load i32, i32* %6
%63 = icmp sge i32 %62, 0
br i1 %63, label %64, label %66
64: ; preds = %61
%65 = load double, double* %5
br label %69
66: ; preds = %61
%67 = load double, double* %5
%68 = fneg double %67
br label %69
69: ; preds = %66, %64
%70 = phi double [ %65, %64 ], [ %68, %66 ]
store double %70, double* %2
br label %71
71: ; preds = %69, %32, %22, %18
%72 = load double, double* %2
ret double %72
}

LLVM IR (-O2):
define double @tanh(double %0) {
%2 = bitcast double %0 to i64
%3 = lshr i64 %2, 32
%4 = trunc i64 %3 to i32
%5 = and i32 %4, 2147483647
%6 = icmp ugt i32 %5, 2146435071
br i1 %6, label %7, label %14
7: ; preds = %1
%8 = icmp sgt i64 %2, -1
%9 = fdiv double 1.000000e+00, %0
br i1 %8, label %10, label %12
10: ; preds = %7
%11 = fadd double %9, 1.000000e+00
br label %41
12: ; preds = %7
%13 = fadd double %9, -1.000000e+00
br label %41
14: ; preds = %1
%15 = icmp ult i32 %5, 1077280768
br i1 %15, label %16, label %36
16: ; preds = %14
%17 = icmp ult i32 %5, 1015021568
br i1 %17, label %18, label %21
18: ; preds = %16
%19 = fadd double %0, 1.000000e+00
%20 = fmul double %19, %0
br label %41
21: ; preds = %16
%22 = icmp ugt i32 %5, 1072693247
%23 = tail call double @llvm.fabs.f64(double %0)
br i1 %22, label %24, label %30
24: ; preds = %21
%25 = fmul double %23, 2.000000e+00
%26 = tail call double @expm1(double %25)
%27 = fadd double %26, 2.000000e+00
%28 = fdiv double 2.000000e+00, %27
%29 = fsub double 1.000000e+00, %28
br label %36
30: ; preds = %21
%31 = fmul double %23, -2.000000e+00
%32 = tail call double @expm1(double %31)
%33 = fneg double %32
%34 = fadd double %32, 2.000000e+00
%35 = fdiv double %33, %34
br label %36
36: ; preds = %14, %24, %30
%37 = phi double [ %29, %24 ], [ %35, %30 ], [ 1.000000e+00, %14 ]
%38 = icmp sgt i64 %2, -1
%39 = fneg double %37
%40 = select i1 %38, double %37, double %39
br label %41
41: ; preds = %36, %18, %12, %10
%42 = phi double [ %11, %10 ], [ %13, %12 ], [ %20, %18 ], [ %40, %36 ]
ret double %42
}