double P10(long exponent) {
  double value, power;
  if (exponent < 0) {
    power = 0.1;
    value = (exponent & 1 ? power : 1.0);
    exponent++;
    exponent = -(exponent >> 1);
  } else {
    power = 10.0;
    value = (exponent & 1 ? power : 1.0);
    exponent = exponent >> 1;
  }
  while (exponent > 0) {
    power *= power;
    if (exponent & 1)
      value *= power;
    exponent >>= 1;
  }
  return (value);
}


x86 assembly (clang, -O0):
<P10>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
cmpq   $0x0,-0x8(%rbp)
jge    117f <P10+0x7f>
movsd  0xef5(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
and    $0x1,%rax
cmp    $0x0,%rax
je     1141 <P10+0x41>
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1153 <P10+0x53>
movsd  0xebf(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1153 <P10+0x53>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rcx
sar    $0x1,%rcx
xor    %eax,%eax
sub    %rcx,%rax
mov    %rax,-0x8(%rbp)
jmp    11d5 <P10+0xd5>
movsd  0xe79(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
and    $0x1,%rax
cmp    $0x0,%rax
je     11ad <P10+0xad>
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
jmp    11bf <P10+0xbf>
movsd  0xe53(%rip),%xmm0
movsd  %xmm0,-0x28(%rbp)
jmp    11bf <P10+0xbf>
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
mov    -0x8(%rbp),%rax
sar    $0x1,%rax
mov    %rax,-0x8(%rbp)
jmp    11da <P10+0xda>
cmpq   $0x0,-0x8(%rbp)
jle    1226 <P10+0x126>
movsd  -0x18(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
and    $0x1,%rax
cmp    $0x0,%rax
je     1215 <P10+0x115>
movsd  -0x18(%rbp),%xmm0
mulsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
mov    -0x8(%rbp),%rax
sar    $0x1,%rax
mov    %rax,-0x8(%rbp)
jmp    11da <P10+0xda>
movsd  -0x10(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<P10>:
xor    %eax,%eax
test   %rdi,%rdi
js     112c <P10+0x2c>
test   $0x1,%dil
sete   %al
lea    0xeeb(%rip),%rcx
movsd  (%rcx,%rax,8),%xmm0
shr    %rdi
movsd  0xefb(%rip),%xmm1
test   %rdi,%rdi
jne    1156 <P10+0x56>
jmp    1187 <P10+0x87>
test   $0x1,%dil
sete   %al
lea    0xed6(%rip),%rcx
movsd  (%rcx,%rax,8),%xmm0
add    $0x1,%rdi
sar    %rdi
neg    %rdi
movsd  0xed7(%rip),%xmm1
test   %rdi,%rdi
je     1187 <P10+0x87>
movsd  0xed2(%rip),%xmm2
jmp    1173 <P10+0x73>
mulsd  %xmm3,%xmm0
mov    %rdi,%rax
shr    %rax
cmp    $0x1,%rdi
mov    %rax,%rdi
jbe    1187 <P10+0x87>
mulsd  %xmm1,%xmm1
movapd %xmm2,%xmm3
test   $0x1,%dil
je     1160 <P10+0x60>
movapd %xmm1,%xmm3
jmp    1160 <P10+0x60>
ret

LLVM IR (-O0):
define double @P10(i64 %0) {
%2 = alloca i64
%3 = alloca double
%4 = alloca double
store i64 %0, i64* %2
%5 = load i64, i64* %2
%6 = icmp slt i64 %5, 0
br i1 %6, label %7, label %21
7: ; preds = %1
store double 1.000000e-01, double* %4
%8 = load i64, i64* %2
%9 = and i64 %8, 1
%10 = icmp ne i64 %9, 0
br i1 %10, label %11, label %13
11: ; preds = %7
%12 = load double, double* %4
br label %14
13: ; preds = %7
br label %14
14: ; preds = %13, %11
%15 = phi double [ %12, %11 ], [ 1.000000e+00, %13 ]
store double %15, double* %3
%16 = load i64, i64* %2
%17 = add nsw i64 %16, 1
store i64 %17, i64* %2
%18 = load i64, i64* %2
%19 = ashr i64 %18, 1
%20 = sub nsw i64 0, %19
store i64 %20, i64* %2
br label %32
21: ; preds = %1
store double 1.000000e+01, double* %4
%22 = load i64, i64* %2
%23 = and i64 %22, 1
%24 = icmp ne i64 %23, 0
br i1 %24, label %25, label %27
25: ; preds = %21
%26 = load double, double* %4
br label %28
27: ; preds = %21
br label %28
28: ; preds = %27, %25
%29 = phi double [ %26, %25 ], [ 1.000000e+00, %27 ]
store double %29, double* %3
%30 = load i64, i64* %2
%31 = ashr i64 %30, 1
store i64 %31, i64* %2
br label %32
32: ; preds = %28, %14
br label %33
33: ; preds = %47, %32
%34 = load i64, i64* %2
%35 = icmp sgt i64 %34, 0
br i1 %35, label %36, label %50
36: ; preds = %33
%37 = load double, double* %4
%38 = load double, double* %4
%39 = fmul double %38, %37
store double %39, double* %4
%40 = load i64, i64* %2
%41 = and i64 %40, 1
%42 = icmp ne i64 %41, 0
br i1 %42, label %43, label %47
43: ; preds = %36
%44 = load double, double* %4
%45 = load double, double* %3
%46 = fmul double %45, %44
store double %46, double* %3
br label %47
47: ; preds = %43, %36
%48 = load i64, i64* %2
%49 = ashr i64 %48, 1
store i64 %49, i64* %2
br label %33
50: ; preds = %33
%51 = load double, double* %3
ret double %51
}

LLVM IR (-O2):
define double @P10(i64 %0) {
%2 = icmp slt i64 %0, 0
%3 = and i64 %0, 1
%4 = icmp eq i64 %3, 0
br i1 %2, label %5, label %10
5: ; preds = %1
%6 = select i1 %4, double 1.000000e+00, double 1.000000e-01
%7 = add nsw i64 %0, 1
%8 = ashr i64 %7, 1
%9 = sub nsw i64 0, %8
br label %13
10: ; preds = %1
%11 = select i1 %4, double 1.000000e+00, double 1.000000e+01
%12 = lshr i64 %0, 1
br label %13
13: ; preds = %10, %5
%14 = phi i64 [ %9, %5 ], [ %12, %10 ]
%15 = phi double [ %6, %5 ], [ %11, %10 ]
%16 = phi double [ 1.000000e-01, %5 ], [ 1.000000e+01, %10 ]
%17 = icmp eq i64 %14, 0
br i1 %17, label %29, label %18
18: ; preds = %13, %18
%19 = phi double [ %22, %18 ], [ %16, %13 ]
%20 = phi double [ %26, %18 ], [ %15, %13 ]
%21 = phi i64 [ %27, %18 ], [ %14, %13 ]
%22 = fmul double %19, %19
%23 = and i64 %21, 1
%24 = icmp eq i64 %23, 0
%25 = select i1 %24, double 1.000000e+00, double %22
%26 = fmul double %20, %25
%27 = lshr i64 %21, 1
%28 = icmp ult i64 %21, 2
br i1 %28, label %29, label %18
29: ; preds = %18, %13
%30 = phi double [ %15, %13 ], [ %26, %18 ]
ret double %30
}