double Tak(double x, double y, double z) {
  if (y >= x)
    return z;
  return Tak(Tak(x - 1, y, z), Tak(y - 1, z, x), Tak(z - 1, x, y));
}


x86 assembly (clang, -O0):
<Tak>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  %xmm2,-0x20(%rbp)
movsd  -0x18(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jb     1146 <Tak+0x36>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11c7 <Tak+0xb7>
movsd  -0x10(%rbp),%xmm0
movsd  0xead(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  -0x18(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm2
call   1030 <Tak@plt>
movsd  %xmm0,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0xe88(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  -0x20(%rbp),%xmm1
movsd  -0x10(%rbp),%xmm2
call   1030 <Tak@plt>
movsd  %xmm0,-0x30(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  0xe63(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  -0x10(%rbp),%xmm1
movsd  -0x18(%rbp),%xmm2
call   1030 <Tak@plt>
movsd  -0x30(%rbp),%xmm1
movaps %xmm0,%xmm2
movsd  -0x28(%rbp),%xmm0
call   1030 <Tak@plt>
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<Tak>:
sub    $0x28,%rsp
ucomisd %xmm0,%xmm1
jae    11b8 <Tak+0xa8>
movapd %xmm1,%xmm3
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movsd  %xmm3,0x8(%rsp)
movsd  %xmm0,0x10(%rsp)
movsd  0xebc(%rip),%xmm1
addsd  %xmm1,%xmm0
movapd %xmm3,%xmm1
movsd  %xmm2,(%rsp)
call   1030 <Tak@plt>
movsd  %xmm0,0x20(%rsp)
movsd  0x8(%rsp),%xmm0
addsd  0xe96(%rip),%xmm0
movsd  (%rsp),%xmm1
movsd  0x10(%rsp),%xmm2
call   1030 <Tak@plt>
movsd  %xmm0,0x18(%rsp)
movsd  (%rsp),%xmm0
addsd  0xe73(%rip),%xmm0
movsd  0x10(%rsp),%xmm1
movsd  0x8(%rsp),%xmm2
call   1030 <Tak@plt>
movapd %xmm0,%xmm2
movsd  0x20(%rsp),%xmm0
movsd  0x18(%rsp),%xmm3
ucomisd %xmm0,%xmm3
jb     1130 <Tak+0x20>
movapd %xmm2,%xmm0
add    $0x28,%rsp
ret

LLVM IR (-O0):
define double @Tak(double %0, double %1, double %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
store double %0, double* %5
store double %1, double* %6
store double %2, double* %7
%8 = load double, double* %6
%9 = load double, double* %5
%10 = fcmp oge double %8, %9
br i1 %10, label %11, label %13
11: ; preds = %3
%12 = load double, double* %7
store double %12, double* %4
br label %30
13: ; preds = %3
%14 = load double, double* %5
%15 = fsub double %14, 1.000000e+00
%16 = load double, double* %6
%17 = load double, double* %7
%18 = call double @Tak(double %15, double %16, double %17)
%19 = load double, double* %6
%20 = fsub double %19, 1.000000e+00
%21 = load double, double* %7
%22 = load double, double* %5
%23 = call double @Tak(double %20, double %21, double %22)
%24 = load double, double* %7
%25 = fsub double %24, 1.000000e+00
%26 = load double, double* %5
%27 = load double, double* %6
%28 = call double @Tak(double %25, double %26, double %27)
%29 = call double @Tak(double %18, double %23, double %28)
store double %29, double* %4
br label %30
30: ; preds = %13, %11
%31 = load double, double* %4
ret double %31
}

LLVM IR (-O2):
define double @Tak(double %0, double %1, double %2) {
%4 = fcmp ult double %1, %0
br i1 %4, label %5, label %16
5: ; preds = %3, %5
%6 = phi double [ %14, %5 ], [ %2, %3 ]
%7 = phi double [ %12, %5 ], [ %1, %3 ]
%8 = phi double [ %10, %5 ], [ %0, %3 ]
%9 = fadd double %8, -1.000000e+00
%10 = tail call double @Tak(double %9, double %7, double %6)
%11 = fadd double %7, -1.000000e+00
%12 = tail call double @Tak(double %11, double %6, double %8)
%13 = fadd double %6, -1.000000e+00
%14 = tail call double @Tak(double %13, double %8, double %7)
%15 = fcmp ult double %12, %10
br i1 %15, label %5, label %16
16: ; preds = %5, %3
%17 = phi double [ %2, %3 ], [ %14, %5 ]
ret double %17
}