#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 exp(double);
double log1p(double);
double log1pexp(double a) {
  if (a <= -37.0) {
    return exp(a);
  } else if (a > -37.0 && a <= 18.0) {
    return log1p(exp(a));
  } else if (a > 18.0 && a <= 33.3) {
    return a + exp(-a);
  } else if (a > 33.3) {
    return a;
  }
  return a;
}


x86 assembly (clang, -O0):
<log1pexp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  0xecb(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     1154 <log1pexp+0x34>
movsd  -0x10(%rbp),%xmm0
call   1030 <exp@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    1241 <log1pexp+0x121>
movsd  -0x10(%rbp),%xmm0
movsd  0xe9f(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1197 <log1pexp+0x77>
movsd  0xe95(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     1197 <log1pexp+0x77>
movsd  -0x10(%rbp),%xmm0
call   1030 <exp@plt>
call   1040 <log1p@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    1241 <log1pexp+0x121>
movsd  -0x10(%rbp),%xmm0
movsd  0xe64(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1202 <log1pexp+0xe2>
movsd  0xe5a(%rip),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     1202 <log1pexp+0xe2>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x10(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
call   1030 <exp@plt>
movaps %xmm0,%xmm1
movsd  -0x18(%rbp),%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1241 <log1pexp+0x121>
movsd  -0x10(%rbp),%xmm0
movsd  0xe01(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1228 <log1pexp+0x108>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1241 <log1pexp+0x121>
jmp    122d <log1pexp+0x10d>
jmp    1232 <log1pexp+0x112>
jmp    1237 <log1pexp+0x117>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<log1pexp>:
sub    $0x18,%rsp
movapd %xmm0,%xmm1
movsd  0xed0(%rip),%xmm0
ucomisd %xmm1,%xmm0
jae    1160 <log1pexp+0x40>
ucomisd 0xec2(%rip),%xmm1
jbe    116d <log1pexp+0x4d>
movsd  0xec0(%rip),%xmm0
ucomisd %xmm1,%xmm0
jb     116d <log1pexp+0x4d>
movapd %xmm1,%xmm0
call   1030 <exp@plt>
add    $0x18,%rsp
jmp    1040 <log1p@plt>
movapd %xmm1,%xmm0
add    $0x18,%rsp
jmp    1030 <exp@plt>
ucomisd 0xe93(%rip),%xmm1
jbe    11a4 <log1pexp+0x84>
movsd  0xe91(%rip),%xmm0
ucomisd %xmm1,%xmm0
jb     11a4 <log1pexp+0x84>
movapd 0xe93(%rip),%xmm0
xorpd  %xmm1,%xmm0
movapd %xmm1,(%rsp)
call   1030 <exp@plt>
movapd (%rsp),%xmm1
addsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
add    $0x18,%rsp
ret

LLVM IR (-O0):
define double @log1pexp(double %0) {
%2 = alloca double
%3 = alloca double
store double %0, double* %3
%4 = load double, double* %3
%5 = fcmp ole double %4, -3.700000e+01
br i1 %5, label %6, label %9
6: ; preds = %1
%7 = load double, double* %3
%8 = call double @exp(double %7)
store double %8, double* %2
br label %41
9: ; preds = %1
%10 = load double, double* %3
%11 = fcmp ogt double %10, -3.700000e+01
br i1 %11, label %12, label %19
12: ; preds = %9
%13 = load double, double* %3
%14 = fcmp ole double %13, 1.800000e+01
br i1 %14, label %15, label %19
15: ; preds = %12
%16 = load double, double* %3
%17 = call double @exp(double %16)
%18 = call double @log1p(double %17)
store double %18, double* %2
br label %41
19: ; preds = %12, %9
%20 = load double, double* %3
%21 = fcmp ogt double %20, 1.800000e+01
br i1 %21, label %22, label %31
22: ; preds = %19
%23 = load double, double* %3
%24 = fcmp ole double %23, 3.330000e+01
br i1 %24, label %25, label %31
25: ; preds = %22
%26 = load double, double* %3
%27 = load double, double* %3
%28 = fneg double %27
%29 = call double @exp(double %28)
%30 = fadd double %26, %29
store double %30, double* %2
br label %41
31: ; preds = %22, %19
%32 = load double, double* %3
%33 = fcmp ogt double %32, 3.330000e+01
br i1 %33, label %34, label %36
34: ; preds = %31
%35 = load double, double* %3
store double %35, double* %2
br label %41
36: ; preds = %31
br label %37
37: ; preds = %36
br label %38
38: ; preds = %37
br label %39
39: ; preds = %38
%40 = load double, double* %3
store double %40, double* %2
br label %41
41: ; preds = %39, %34, %25, %15, %6
%42 = load double, double* %2
ret double %42
}

LLVM IR (-O2):
define double @log1pexp(double %0) {
%2 = fcmp ugt double %0, -3.700000e+01
br i1 %2, label %5, label %3
3: ; preds = %1
%4 = tail call double @exp(double %0)
br label %20
5: ; preds = %1
%6 = fcmp ogt double %0, -3.700000e+01
%7 = fcmp ole double %0, 1.800000e+01
%8 = and i1 %6, %7
br i1 %8, label %9, label %12
9: ; preds = %5
%10 = tail call double @exp(double %0)
%11 = tail call double @log1p(double %10)
br label %20
12: ; preds = %5
%13 = fcmp ogt double %0, 1.800000e+01
%14 = fcmp ole double %0, 3.330000e+01
%15 = and i1 %13, %14
br i1 %15, label %16, label %20
16: ; preds = %12
%17 = fneg double %0
%18 = tail call double @exp(double %17)
%19 = fadd double %18, %0
br label %20
20: ; preds = %12, %16, %9, %3
%21 = phi double [ %4, %3 ], [ %11, %9 ], [ %19, %16 ], [ %0, %12 ]
ret double %21
}