double tanh(x)
double x;
{
  static double one = 1.0, two = 2.0, small = 1.0e-10, big = 1.0e10;
  double expm1(), t, copysign(), sign;
  int finite(), isnan();
  if (x != x)
    return (x);
  sign = copysign(one, x);
  x = copysign(x, one);
  if (x < 22.0)
    if (x > one)
      return (copysign(one - two / (expm1(x + x) + two), sign));
    else if (x > small) {
      t = -expm1(-(x + x));
      return (copysign(t / (two - t), sign));
    } else {
      t = big + x;
      return (copysign(x, sign));
    }
  else if (finite(x))
    return (sign + 1.0E-37);
  else
    return (sign);
}


x86 assembly (clang, -O0):
<tanh>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jne    1138 <tanh+0x28>
jp     1138 <tanh+0x28>
jmp    1147 <tanh+0x37>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    134b <tanh+0x23b>
movsd  0x2ed9(%rip),%xmm0
movsd  -0x10(%rbp),%xmm1
movaps 0xec5(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xeca(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  0x2ea8(%rip),%xmm1
movaps 0xe99(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xe9e(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  0xe59(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    1308 <tanh+0x1f8>
movsd  -0x10(%rbp),%xmm0
ucomisd 0x2e69(%rip),%xmm0
jbe    1234 <tanh+0x124>
movsd  0x2e5b(%rip),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  0x2e56(%rip),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x10(%rbp),%xmm0
addsd  -0x10(%rbp),%xmm0
call   1030 <expm1@plt>
movsd  -0x30(%rbp),%xmm1
movaps %xmm0,%xmm2
movsd  -0x28(%rbp),%xmm0
addsd  0x2e2d(%rip),%xmm2
divsd  %xmm2,%xmm1
subsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movaps 0xe09(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xe0e(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    134b <tanh+0x23b>
movsd  -0x10(%rbp),%xmm0
ucomisd 0x2df7(%rip),%xmm0
jbe    12c8 <tanh+0x1b8>
movsd  -0x10(%rbp),%xmm0
addsd  -0x10(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
call   1030 <expm1@plt>
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0x2d9a(%rip),%xmm1
subsd  -0x18(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movaps 0xd75(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xd7a(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    134b <tanh+0x23b>
movsd  0x2d70(%rip),%xmm0
addsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm1
movaps 0xd35(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xd3a(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    134b <tanh+0x23b>
movsd  -0x10(%rbp),%xmm0
movaps 0xd1c(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  0xce8(%rip),%xmm1
ucomisd %xmm1,%xmm0
je     1341 <tanh+0x231>
movsd  0xcde(%rip),%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    134b <tanh+0x23b>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<tanh>:
sub    $0x18,%rsp
movapd %xmm0,%xmm2
ucomisd %xmm0,%xmm0
jp     11ac <tanh+0x9c>
movapd 0xed6(%rip),%xmm3
andpd  %xmm2,%xmm3
movapd 0xeea(%rip),%xmm0
andpd  %xmm2,%xmm0
movsd  0xeee(%rip),%xmm1
ucomisd %xmm0,%xmm1
jbe    118e <tanh+0x7e>
ucomisd 0xef8(%rip),%xmm0
jbe    11b5 <tanh+0xa5>
addsd  %xmm0,%xmm0
movapd %xmm3,(%rsp)
call   1030 <expm1@plt>
movsd  0xef0(%rip),%xmm1
addsd  %xmm1,%xmm0
divsd  %xmm0,%xmm1
movsd  0xed0(%rip),%xmm0
subsd  %xmm1,%xmm0
andpd  0xe9c(%rip),%xmm0
orpd   (%rsp),%xmm0
add    $0x18,%rsp
ret
orpd   0xe7a(%rip),%xmm3
ucomisd 0xe9a(%rip),%xmm0
je     11a8 <tanh+0x98>
addsd  0xe98(%rip),%xmm3
movapd %xmm3,%xmm2
movapd %xmm2,%xmm0
add    $0x18,%rsp
ret
ucomisd 0xe93(%rip),%xmm0
jbe    11ac <tanh+0x9c>
addsd  %xmm0,%xmm0
xorpd  0xe35(%rip),%xmm0
movapd %xmm2,(%rsp)
call   1030 <expm1@plt>
movapd 0xe23(%rip),%xmm1
xorpd  %xmm0,%xmm1
addsd  0xe6f(%rip),%xmm0
divsd  %xmm0,%xmm1
movapd 0xe2b(%rip),%xmm0
andpd  %xmm0,%xmm1
andnpd (%rsp),%xmm0
orpd   %xmm1,%xmm0
add    $0x18,%rsp
ret

LLVM IR (-O0):
@tanh.one = internal global double 1.000000e+00
@tanh.two = internal global double 2.000000e+00
@tanh.small = internal global double 1.000000e-10
@tanh.big = internal global double 1.000000e+10
define double @tanh(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
store double %0, double* %3
%6 = load double, double* %3
%7 = load double, double* %3
%8 = fcmp une double %6, %7
br i1 %8, label %9, label %11
9: ; preds = %1
%10 = load double, double* %3
store double %10, double* %2
br label %71
11: ; preds = %1
%12 = load double, double* @tanh.one
%13 = load double, double* %3
%14 = call double @llvm.copysign.f64(double %12, double %13)
store double %14, double* %5
%15 = load double, double* %3
%16 = load double, double* @tanh.one
%17 = call double @llvm.copysign.f64(double %15, double %16)
store double %17, double* %3
%18 = load double, double* %3
%19 = fcmp olt double %18, 2.200000e+01
br i1 %19, label %20, label %62
20: ; preds = %11
%21 = load double, double* %3
%22 = load double, double* @tanh.one
%23 = fcmp ogt double %21, %22
br i1 %23, label %24, label %37
24: ; preds = %20
%25 = load double, double* @tanh.one
%26 = load double, double* @tanh.two
%27 = load double, double* %3
%28 = load double, double* %3
%29 = fadd double %27, %28
%30 = call double @expm1(double %29)
%31 = load double, double* @tanh.two
%32 = fadd double %30, %31
%33 = fdiv double %26, %32
%34 = fsub double %25, %33
%35 = load double, double* %5
%36 = call double @llvm.copysign.f64(double %34, double %35)
store double %36, double* %2
br label %71
37: ; preds = %20
%38 = load double, double* %3
%39 = load double, double* @tanh.small
%40 = fcmp ogt double %38, %39
br i1 %40, label %41, label %55
41: ; preds = %37
%42 = load double, double* %3
%43 = load double, double* %3
%44 = fadd double %42, %43
%45 = fneg double %44
%46 = call double @expm1(double %45)
%47 = fneg double %46
store double %47, double* %4
%48 = load double, double* %4
%49 = load double, double* @tanh.two
%50 = load double, double* %4
%51 = fsub double %49, %50
%52 = fdiv double %48, %51
%53 = load double, double* %5
%54 = call double @llvm.copysign.f64(double %52, double %53)
store double %54, double* %2
br label %71
55: ; preds = %37
%56 = load double, double* @tanh.big
%57 = load double, double* %3
%58 = fadd double %56, %57
store double %58, double* %4
%59 = load double, double* %3
%60 = load double, double* %5
%61 = call double @llvm.copysign.f64(double %59, double %60)
store double %61, double* %2
br label %71
62: ; preds = %11
%63 = load double, double* %3
%64 = call double @llvm.fabs.f64(double %63)
%65 = fcmp one double %64, 0x7FF0000000000000
br i1 %65, label %66, label %69
66: ; preds = %62
%67 = load double, double* %5
%68 = fadd double %67, 1.000000e-37
store double %68, double* %2
br label %71
69: ; preds = %62
%70 = load double, double* %5
store double %70, double* %2
br label %71
71: ; preds = %69, %66, %55, %41, %24, %9
%72 = load double, double* %2
ret double %72
}

LLVM IR (-O2):
define double @tanh(double %0) {
%2 = fcmp uno double %0, 0.000000e+00
br i1 %2, label %30, label %3
3: ; preds = %1
%4 = tail call double @llvm.copysign.f64(double 1.000000e+00, double %0)
%5 = tail call double @llvm.fabs.f64(double %0)
%6 = fcmp olt double %5, 2.200000e+01
br i1 %6, label %7, label %26
7: ; preds = %3
%8 = fcmp ogt double %5, 1.000000e+00
br i1 %8, label %9, label %16
9: ; preds = %7
%10 = fadd double %5, %5
%11 = tail call double @expm1(double %10)
%12 = fadd double %11, 2.000000e+00
%13 = fdiv double 2.000000e+00, %12
%14 = fsub double 1.000000e+00, %13
%15 = tail call double @llvm.copysign.f64(double %14, double %0)
br label %30
16: ; preds = %7
%17 = fcmp ogt double %5, 1.000000e-10
br i1 %17, label %18, label %30
18: ; preds = %16
%19 = fadd double %5, %5
%20 = fneg double %19
%21 = tail call double @expm1(double %20)
%22 = fneg double %21
%23 = fadd double %21, 2.000000e+00
%24 = fdiv double %22, %23
%25 = tail call double @llvm.copysign.f64(double %24, double %0)
br label %30
26: ; preds = %3
%27 = fcmp ueq double %5, 0x7FF0000000000000
br i1 %27, label %30, label %28
28: ; preds = %26
%29 = fadd double %4, 1.000000e-37
br label %30
30: ; preds = %26, %16, %1, %28, %18, %9
%31 = phi double [ %15, %9 ], [ %25, %18 ], [ %29, %28 ], [ %0, %1 ], [ %0, %16 ], [ %4, %26 ]
ret double %31
}