double exponential(int x, int n) {
  static double s;
  if (n == 0) {
    return s;
  }
  s = 1 + x * (s / n);
  return exponential(x, n - 1);
}


x86 assembly (clang, -O0):
<exponential>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %edi,-0xc(%rbp)
mov    %esi,-0x10(%rbp)
cmpl   $0x0,-0x10(%rbp)
jne    113a <exponential+0x2a>
movsd  0x2f00(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    117b <exponential+0x6b>
cvtsi2sdl -0xc(%rbp),%xmm0
movsd  0x2ee9(%rip),%xmm1
cvtsi2sdl -0x10(%rbp),%xmm2
divsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  0xea4(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,0x2ec8(%rip)
mov    -0xc(%rbp),%edi
mov    -0x10(%rbp),%esi
sub    $0x1,%esi
call   1030 <exponential@plt>
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<exponential>:
movsd  0x2f20(%rip),%xmm0
test   %esi,%esi
je     1186 <exponential+0x86>
cvtsi2sd %edi,%xmm1
test   $0x1,%sil
jne    111f <exponential+0x1f>
mov    %esi,%eax
cmp    $0x1,%esi
jne    113b <exponential+0x3b>
jmp    117e <exponential+0x7e>
cvtsi2sd %esi,%xmm2
divsd  %xmm2,%xmm0
mulsd  %xmm1,%xmm0
addsd  0xecd(%rip),%xmm0
lea    -0x1(%rsi),%eax
cmp    $0x1,%esi
je     117e <exponential+0x7e>
movsd  0xebd(%rip),%xmm2
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
xorps  %xmm3,%xmm3
cvtsi2sd %eax,%xmm3
divsd  %xmm3,%xmm0
mulsd  %xmm1,%xmm0
addsd  %xmm2,%xmm0
lea    -0x1(%rax),%ecx
xorps  %xmm3,%xmm3
cvtsi2sd %ecx,%xmm3
divsd  %xmm3,%xmm0
mulsd  %xmm1,%xmm0
addsd  %xmm2,%xmm0
add    $0xfffffffe,%eax
jne    1150 <exponential+0x50>
movsd  %xmm0,0x2ea2(%rip)
ret

LLVM IR (-O0):
@exponential.s = internal global double 0.000000e+00
define double @exponential(i32 %0, i32 %1) {
%3 = alloca double
%4 = alloca i32
%5 = alloca i32
store i32 %0, i32* %4
store i32 %1, i32* %5
%6 = load i32, i32* %5
%7 = icmp eq i32 %6, 0
br i1 %7, label %8, label %10
8: ; preds = %2
%9 = load double, double* @exponential.s
store double %9, double* %3
br label %22
10: ; preds = %2
%11 = load i32, i32* %4
%12 = sitofp i32 %11 to double
%13 = load double, double* @exponential.s
%14 = load i32, i32* %5
%15 = sitofp i32 %14 to double
%16 = fdiv double %13, %15
%17 = call double @llvm.fmuladd.f64(double %12, double %16, double 1.000000e+00)
store double %17, double* @exponential.s
%18 = load i32, i32* %4
%19 = load i32, i32* %5
%20 = sub nsw i32 %19, 1
%21 = call double @exponential(i32 %18, i32 %20)
store double %21, double* %3
br label %22
22: ; preds = %10, %8
%23 = load double, double* %3
ret double %23
}

LLVM IR (-O2):
@exponential.s = internal unnamed_addr global double 0.000000e+00
define double @exponential(i32 %0, i32 %1) {
%3 = icmp eq i32 %1, 0
%4 = load double, double* @exponential.s
br i1 %3, label %21, label %5
5: ; preds = %2
%6 = sitofp i32 %0 to double
%7 = and i32 %1, 1
%8 = icmp eq i32 %7, 0
br i1 %8, label %14, label %9
9: ; preds = %5
%10 = sitofp i32 %1 to double
%11 = fdiv double %4, %10
%12 = tail call double @llvm.fmuladd.f64(double %6, double %11, double 1.000000e+00)
%13 = add nsw i32 %1, -1
br label %14
14: ; preds = %9, %5
%15 = phi double [ undef, %5 ], [ %12, %9 ]
%16 = phi i32 [ %1, %5 ], [ %13, %9 ]
%17 = phi double [ %4, %5 ], [ %12, %9 ]
%18 = icmp eq i32 %1, 1
br i1 %18, label %19, label %23
19: ; preds = %23, %14
%20 = phi double [ %15, %14 ], [ %32, %23 ]
store double %20, double* @exponential.s
br label %21
21: ; preds = %2, %19
%22 = phi double [ %20, %19 ], [ %4, %2 ]
ret double %22
23: ; preds = %14, %23
%24 = phi i32 [ %33, %23 ], [ %16, %14 ]
%25 = phi double [ %32, %23 ], [ %17, %14 ]
%26 = sitofp i32 %24 to double
%27 = fdiv double %25, %26
%28 = tail call double @llvm.fmuladd.f64(double %6, double %27, double 1.000000e+00)
%29 = add nsw i32 %24, -1
%30 = sitofp i32 %29 to double
%31 = fdiv double %28, %30
%32 = tail call double @llvm.fmuladd.f64(double %6, double %31, double 1.000000e+00)
%33 = add nsw i32 %24, -2
%34 = icmp eq i32 %33, 0
br i1 %34, label %19, label %23
}