double binary(double x, int n) {
  double res;
  if (n == 1)
    return x;
  else if (n == 0)
    return 1;
  res = binary(x, n / 2);
  res *= res;
  return (n & 1) == 1 ? res * x : res;
}


x86 assembly (clang, -O0):
<binary>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
movsd  %xmm0,-0x10(%rbp)
mov    %edi,-0x14(%rbp)
cmpl   $0x1,-0x14(%rbp)
jne    1139 <binary+0x29>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11bc <binary+0xac>
cmpl   $0x0,-0x14(%rbp)
jne    1155 <binary+0x45>
movsd  0xeb5(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11bc <binary+0xac>
jmp    115a <binary+0x4a>
movsd  -0x10(%rbp),%xmm0
mov    -0x14(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
mov    %eax,%edi
call   1030 <binary@plt>
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x14(%rbp),%eax
and    $0x1,%eax
cmp    $0x1,%eax
jne    11a8 <binary+0x98>
movsd  -0x20(%rbp),%xmm0
mulsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
jmp    11b2 <binary+0xa2>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<binary>:
push   %rbx
sub    $0x10,%rsp
movapd %xmm0,%xmm1
cmp    $0x1,%edi
je     1163 <binary+0x53>
mov    %edi,%ebx
test   %edi,%edi
jne    112e <binary+0x1e>
movsd  0xed4(%rip),%xmm1
jmp    1163 <binary+0x53>
mov    %ebx,%edi
shr    $0x1f,%edi
add    %ebx,%edi
sar    %edi
movsd  %xmm1,0x8(%rsp)
movapd %xmm1,%xmm0
call   1030 <binary@plt>
mulsd  %xmm0,%xmm0
test   $0x1,%bl
je     1157 <binary+0x47>
movsd  0x8(%rsp),%xmm1
jmp    115f <binary+0x4f>
movsd  0xea1(%rip),%xmm1
mulsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define double @binary(double %0, i32 %1) {
%3 = alloca double
%4 = alloca double
%5 = alloca i32
%6 = alloca double
store double %0, double* %4
store i32 %1, i32* %5
%7 = load i32, i32* %5
%8 = icmp eq i32 %7, 1
br i1 %8, label %9, label %11
9: ; preds = %2
%10 = load double, double* %4
store double %10, double* %3
br label %35
11: ; preds = %2
%12 = load i32, i32* %5
%13 = icmp eq i32 %12, 0
br i1 %13, label %14, label %15
14: ; preds = %11
store double 1.000000e+00, double* %3
br label %35
15: ; preds = %11
br label %16
16: ; preds = %15
%17 = load double, double* %4
%18 = load i32, i32* %5
%19 = sdiv i32 %18, 2
%20 = call double @binary(double %17, i32 %19)
store double %20, double* %6
%21 = load double, double* %6
%22 = load double, double* %6
%23 = fmul double %22, %21
store double %23, double* %6
%24 = load i32, i32* %5
%25 = and i32 %24, 1
%26 = icmp eq i32 %25, 1
br i1 %26, label %27, label %31
27: ; preds = %16
%28 = load double, double* %6
%29 = load double, double* %4
%30 = fmul double %28, %29
br label %33
31: ; preds = %16
%32 = load double, double* %6
br label %33
33: ; preds = %31, %27
%34 = phi double [ %30, %27 ], [ %32, %31 ]
store double %34, double* %3
br label %35
35: ; preds = %33, %14, %9
%36 = load double, double* %3
ret double %36
}

LLVM IR (-O2):
define double @binary(double %0, i32 %1) {
switch i32 %1, label %6 [
i32 1, label %4
i32 0, label %3
]
3: ; preds = %2
br label %4
4: ; preds = %3, %2, %6
%5 = phi double [ %13, %6 ], [ 1.000000e+00, %3 ], [ %0, %2 ]
ret double %5
6: ; preds = %2
%7 = sdiv i32 %1, 2
%8 = tail call double @binary(double %0, i32 %7)
%9 = fmul double %8, %8
%10 = and i32 %1, 1
%11 = icmp eq i32 %10, 0
%12 = select i1 %11, double 1.000000e+00, double %0
%13 = fmul double %12, %9
br label %4
}