#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);
float fabs(double);
double rexp(double x) {
  static double p1 = 9.14041914819518e-10;
  static double p2 = .0238082361044469;
  static double q1 = -.499999999085958;
  static double q2 = .107141568980644;
  static double q3 = -.0119041179760821;
  static double q4 = 5.95130811860248e-4;
  double ret_val;
  double w;
  if (fabs(x) > .15f) {
    goto L10;
  }
  ret_val = x * (((p2 * x + p1) * x + 1.0) /
                 ((((q4 * x + q3) * x + q2) * x + q1) * x + 1.0));
  return ret_val;
L10:
  w = exp(x);
  if (x > 0.0) {
    goto L20;
  }
  ret_val = w - 0.5 - 0.5;
  return ret_val;
L20:
  ret_val = w * (0.5 - 1.0 / w + 0.5);
  return ret_val;
}


x86 assembly (clang, -O0):
<rexp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
call   1030 <fabs@plt>
movss  0xec1(%rip),%xmm1
ucomiss %xmm1,%xmm0
jbe    114d <rexp+0x2d>
jmp    11fc <rexp+0xdc>
movsd  -0x10(%rbp),%xmm0
movsd  0x2ede(%rip),%xmm1
movsd  -0x10(%rbp),%xmm3
movsd  0x2ec9(%rip),%xmm2
mulsd  %xmm3,%xmm1
addsd  %xmm2,%xmm1
movsd  -0x10(%rbp),%xmm2
mulsd  %xmm2,%xmm1
movsd  0xe88(%rip),%xmm2
addsd  %xmm2,%xmm1
movsd  0x2ecc(%rip),%xmm2
movsd  -0x10(%rbp),%xmm4
movsd  0x2eb7(%rip),%xmm3
mulsd  %xmm4,%xmm2
addsd  %xmm3,%xmm2
movsd  -0x10(%rbp),%xmm4
movsd  0x2e9a(%rip),%xmm3
mulsd  %xmm4,%xmm2
addsd  %xmm3,%xmm2
movsd  -0x10(%rbp),%xmm4
movsd  0x2e7d(%rip),%xmm3
mulsd  %xmm4,%xmm2
addsd  %xmm3,%xmm2
movsd  -0x10(%rbp),%xmm3
mulsd  %xmm3,%xmm2
movsd  0xe2c(%rip),%xmm3
addsd  %xmm3,%xmm2
divsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1290 <rexp+0x170>
movsd  -0x10(%rbp),%xmm0
call   1040 <exp@plt>
movsd  %xmm0,-0x20(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    1222 <rexp+0x102>
jmp    1253 <rexp+0x133>
movsd  -0x20(%rbp),%xmm0
movsd  0xde1(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  0xdd5(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1290 <rexp+0x170>
movsd  -0x20(%rbp),%xmm0
movsd  0xda8(%rip),%xmm2
divsd  -0x20(%rbp),%xmm2
movsd  0xda3(%rip),%xmm1
subsd  %xmm2,%xmm1
movsd  0xd97(%rip),%xmm2
addsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<rexp>:
sub    $0x18,%rsp
movaps %xmm0,(%rsp)
call   1030 <fabs@plt>
ucomiss 0xecc(%rip),%xmm0
jbe    1178 <rexp+0x58>
movapd (%rsp),%xmm0
call   1040 <exp@plt>
xorpd  %xmm1,%xmm1
movapd (%rsp),%xmm2
ucomisd %xmm1,%xmm2
jbe    11e6 <rexp+0xc6>
movsd  0xecd(%rip),%xmm1
divsd  %xmm0,%xmm1
movsd  0xec9(%rip),%xmm2
addsd  %xmm2,%xmm1
addsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
add    $0x18,%rsp
ret
movsd  0xe88(%rip),%xmm0
movapd (%rsp),%xmm3
mulsd  %xmm3,%xmm0
addsd  0xe7f(%rip),%xmm0
mulsd  %xmm3,%xmm0
addsd  0xe7b(%rip),%xmm0
movapd %xmm3,%xmm1
unpcklpd %xmm0,%xmm1
movapd 0xe93(%rip),%xmm2
unpcklpd %xmm3,%xmm2
mulpd  %xmm1,%xmm2
addpd  0xe93(%rip),%xmm2
movapd %xmm3,%xmm0
unpcklpd %xmm3,%xmm0
mulpd  %xmm2,%xmm0
addpd  0xe8f(%rip),%xmm0
movapd %xmm0,%xmm1
unpckhpd %xmm0,%xmm1
divsd  %xmm1,%xmm0
mulsd  %xmm3,%xmm0
add    $0x18,%rsp
ret
movsd  0xe32(%rip),%xmm1
addsd  %xmm1,%xmm0
addsd  %xmm1,%xmm0
add    $0x18,%rsp
ret

LLVM IR (-O0):
@rexp.p1 = internal global double 0x3E0F67FF69DA8D77
@rexp.p2 = internal global double 0x3F98612FADC6B3F6
@rexp.q1 = internal global double 0xBFDFFFFFFF04C003
@rexp.q2 = internal global double 0x3FBB6DA13ED061EA
@rexp.q3 = internal global double 0xBF88612FAB28F4E2
@rexp.q4 = internal global double 0x3F438051AFD8141C
define double @rexp(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 = call float @fabs(double %6)
%8 = fcmp ogt float %7, 0x3FC3333340000000
br i1 %8, label %9, label %10
9: ; preds = %1
br label %33
10: ; preds = %1
%11 = load double, double* %3
%12 = load double, double* @rexp.p2
%13 = load double, double* %3
%14 = load double, double* @rexp.p1
%15 = call double @llvm.fmuladd.f64(double %12, double %13, double %14)
%16 = load double, double* %3
%17 = call double @llvm.fmuladd.f64(double %15, double %16, double 1.000000e+00)
%18 = load double, double* @rexp.q4
%19 = load double, double* %3
%20 = load double, double* @rexp.q3
%21 = call double @llvm.fmuladd.f64(double %18, double %19, double %20)
%22 = load double, double* %3
%23 = load double, double* @rexp.q2
%24 = call double @llvm.fmuladd.f64(double %21, double %22, double %23)
%25 = load double, double* %3
%26 = load double, double* @rexp.q1
%27 = call double @llvm.fmuladd.f64(double %24, double %25, double %26)
%28 = load double, double* %3
%29 = call double @llvm.fmuladd.f64(double %27, double %28, double 1.000000e+00)
%30 = fdiv double %17, %29
%31 = fmul double %11, %30
store double %31, double* %4
%32 = load double, double* %4
store double %32, double* %2
br label %52
33: ; preds = %9
%34 = load double, double* %3
%35 = call double @exp(double %34)
store double %35, double* %5
%36 = load double, double* %3
%37 = fcmp ogt double %36, 0.000000e+00
br i1 %37, label %38, label %39
38: ; preds = %33
br label %44
39: ; preds = %33
%40 = load double, double* %5
%41 = fsub double %40, 5.000000e-01
%42 = fsub double %41, 5.000000e-01
store double %42, double* %4
%43 = load double, double* %4
store double %43, double* %2
br label %52
44: ; preds = %38
%45 = load double, double* %5
%46 = load double, double* %5
%47 = fdiv double 1.000000e+00, %46
%48 = fsub double 5.000000e-01, %47
%49 = fadd double %48, 5.000000e-01
%50 = fmul double %45, %49
store double %50, double* %4
%51 = load double, double* %4
store double %51, double* %2
br label %52
52: ; preds = %44, %39, %10
%53 = load double, double* %2
ret double %53
}

LLVM IR (-O2):
define double @rexp(double %0) {
%2 = tail call float @fabs(double %0)
%3 = fcmp ogt float %2, 0x3FC3333340000000
br i1 %3, label %17, label %4
4: ; preds = %1
%5 = tail call double @llvm.fmuladd.f64(double %0, double 0x3F438051AFD8141C, double 0xBF88612FAB28F4E2)
%6 = tail call double @llvm.fmuladd.f64(double %5, double %0, double 0x3FBB6DA13ED061EA)
%7 = insertelement <2 x double> poison, double %0, i64 0
%8 = insertelement <2 x double> %7, double %6, i64 1
%9 = insertelement <2 x double> <double 0x3F98612FADC6B3F6, double poison>, double %0, i64 1
%10 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %8, <2 x double> %9, <2 x double> <double 0x3E0F67FF69DA8D77, double 0xBFDFFFFFFF04C003>)
%11 = shufflevector <2 x double> %7, <2 x double> poison, <2 x i32> zeroinitializer
%12 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %10, <2 x double> %11, <2 x double> <double 1.000000e+00, double 1.000000e+00>)
%13 = extractelement <2 x double> %12, i64 0
%14 = extractelement <2 x double> %12, i64 1
%15 = fdiv double %13, %14
%16 = fmul double %15, %0
br label %28
17: ; preds = %1
%18 = tail call double @exp(double %0)
%19 = fcmp ogt double %0, 0.000000e+00
br i1 %19, label %23, label %20
20: ; preds = %17
%21 = fadd double %18, -5.000000e-01
%22 = fadd double %21, -5.000000e-01
br label %28
23: ; preds = %17
%24 = fdiv double 1.000000e+00, %18
%25 = fsub double 5.000000e-01, %24
%26 = fadd double %25, 5.000000e-01
%27 = fmul double %18, %26
br label %28
28: ; preds = %23, %20, %4
%29 = phi double [ %27, %23 ], [ %22, %20 ], [ %16, %4 ]
ret double %29
}