double airIntPow(double v, int p) {
  double sq, ret;
  if (p > 0) {
    sq = v;
    while (!(p & 1)) {
      p >>= 1;
      sq *= sq;
    }
    ret = sq;
    while (p >>= 1) {
      sq *= sq;
      if (p & 1) {
        ret *= sq;
      }
    }
  } else if (p < 0) {
    ret = airIntPow(1.0 / v, -p);
  } else {
    ret = 1.0;
  }
  return ret;
}


x86 assembly (clang, -O0):
<airIntPow>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
movsd  %xmm0,-0x8(%rbp)
mov    %edi,-0xc(%rbp)
cmpl   $0x0,-0xc(%rbp)
jle    11bf <airIntPow+0xaf>
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0xc(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
setne  %al
xor    $0xff,%al
test   $0x1,%al
jne    114f <airIntPow+0x3f>
jmp    116c <airIntPow+0x5c>
mov    -0xc(%rbp),%eax
sar    $0x1,%eax
mov    %eax,-0xc(%rbp)
movsd  -0x18(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    1134 <airIntPow+0x24>
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0xc(%rbp),%eax
sar    $0x1,%eax
mov    %eax,-0xc(%rbp)
cmp    $0x0,%eax
je     11ba <airIntPow+0xaa>
movsd  -0x18(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0xc(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     11b5 <airIntPow+0xa5>
movsd  -0x18(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1176 <airIntPow+0x66>
jmp    11fc <airIntPow+0xec>
cmpl   $0x0,-0xc(%rbp)
jge    11ea <airIntPow+0xda>
movsd  0xe2f(%rip),%xmm0
divsd  -0x8(%rbp),%xmm0
xor    %edi,%edi
sub    -0xc(%rbp),%edi
call   1030 <airIntPow@plt>
movsd  %xmm0,-0x20(%rbp)
jmp    11f7 <airIntPow+0xe7>
movsd  0xe0e(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    11fc <airIntPow+0xec>
movsd  -0x20(%rbp),%xmm0
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<airIntPow>:
test   %edi,%edi
jle    1125 <airIntPow+0x25>
test   $0x1,%dil
jne    1148 <airIntPow+0x48>
mov    %edi,%eax
nopl   0x0(%rax)
sar    %eax
mulsd  %xmm0,%xmm0
test   $0x2,%dil
mov    %eax,%edi
je     1110 <airIntPow+0x10>
cmp    $0x2,%eax
jb     114f <airIntPow+0x4f>
jmp    1150 <airIntPow+0x50>
js     1130 <airIntPow+0x30>
movsd  0xed1(%rip),%xmm0
ret
movsd  0xec8(%rip),%xmm1
divsd  %xmm0,%xmm1
neg    %edi
movapd %xmm1,%xmm0
test   $0x1,%dil
je     110a <airIntPow+0xa>
mov    %edi,%eax
cmp    $0x2,%eax
jae    1150 <airIntPow+0x50>
ret
movsd  0xea8(%rip),%xmm1
movapd %xmm0,%xmm2
jmp    116f <airIntPow+0x6f>
xchg   %ax,%ax
mulsd  %xmm3,%xmm0
mov    %eax,%ecx
sar    %ecx
cmp    $0x4,%eax
mov    %ecx,%eax
jb     114f <airIntPow+0x4f>
mulsd  %xmm2,%xmm2
movapd %xmm1,%xmm3
test   $0x2,%al
je     1160 <airIntPow+0x60>
movapd %xmm2,%xmm3
jmp    1160 <airIntPow+0x60>

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

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