double ipow(double a, int b) {
  double val = 1.0;
  if (b < 0) {
    while (b++) {
      val *= a;
    }
    val = 1.0 / val;
  } else {
    while (b--) {
      val *= a;
    }
  }
  return val;
}


x86 assembly (clang, -O0):
<ipow>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
mov    %edi,-0xc(%rbp)
movsd  0xeec(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
cmpl   $0x0,-0xc(%rbp)
jge    1167 <ipow+0x67>
jmp    1128 <ipow+0x28>
mov    -0xc(%rbp),%eax
mov    %eax,%ecx
add    $0x1,%ecx
mov    %ecx,-0xc(%rbp)
cmp    $0x0,%eax
je     1150 <ipow+0x50>
movsd  -0x8(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    1128 <ipow+0x28>
movsd  0xea8(%rip),%xmm0
divsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    1199 <ipow+0x99>
jmp    116c <ipow+0x6c>
mov    -0xc(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0xc(%rbp)
cmp    $0x0,%eax
je     1194 <ipow+0x94>
movsd  -0x8(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    116c <ipow+0x6c>
jmp    1199 <ipow+0x99>
movsd  -0x18(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<ipow>:
test   %edi,%edi
js     117a <ipow+0x7a>
je     11f6 <ipow+0xf6>
lea    -0x1(%rdi),%eax
mov    %edi,%ecx
and    $0x7,%ecx
je     11ff <ipow+0xff>
xor    %edx,%edx
movsd  0xede(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mulsd  %xmm0,%xmm1
add    $0x1,%edx
cmp    %edx,%ecx
jne    1130 <ipow+0x30>
sub    %edx,%edi
cmp    $0x7,%eax
jb     1175 <ipow+0x75>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
add    $0xfffffff8,%edi
jne    1150 <ipow+0x50>
movapd %xmm1,%xmm0
ret
mov    %edi,%eax
neg    %eax
and    $0x7,%eax
je     1215 <ipow+0x115>
neg    %eax
movsd  0xe6f(%rip),%xmm2
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
mulsd  %xmm0,%xmm2
add    $0xffffffff,%ecx
cmp    %ecx,%eax
jne    11a0 <ipow+0xa0>
mov    %edi,%eax
sub    %ecx,%eax
cmp    $0xfffffff8,%edi
ja     11e5 <ipow+0xe5>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm2
add    $0x8,%eax
jne    11c0 <ipow+0xc0>
movsd  0xe13(%rip),%xmm1
divsd  %xmm2,%xmm1
movapd %xmm1,%xmm0
ret
movsd  0xe02(%rip),%xmm0
ret
movsd  0xdf9(%rip),%xmm1
cmp    $0x7,%eax
jae    1150 <ipow+0x50>
jmp    1175 <ipow+0x75>
movsd  0xde3(%rip),%xmm2
mov    %edi,%eax
cmp    $0xfffffff8,%edi
jbe    11c0 <ipow+0xc0>
jmp    11e5 <ipow+0xe5>

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

LLVM IR (-O2):
define double @ipow(double %0, i32 %1) {
%3 = icmp slt i32 %1, 0
br i1 %3, label %4, label %21
4: ; preds = %2
%5 = sub i32 0, %1
%6 = and i32 %5, 7
%7 = icmp eq i32 %6, 0
br i1 %7, label %16, label %8
8: ; preds = %4, %8
%9 = phi double [ %13, %8 ], [ 1.000000e+00, %4 ]
%10 = phi i32 [ %12, %8 ], [ %1, %4 ]
%11 = phi i32 [ %14, %8 ], [ 0, %4 ]
%12 = add nsw i32 %10, 1
%13 = fmul double %9, %0
%14 = add i32 %11, 1
%15 = icmp eq i32 %14, %6
br i1 %15, label %16, label %8
16: ; preds = %8, %4
%17 = phi double [ undef, %4 ], [ %13, %8 ]
%18 = phi double [ 1.000000e+00, %4 ], [ %13, %8 ]
%19 = phi i32 [ %1, %4 ], [ %12, %8 ]
%20 = icmp ugt i32 %1, -8
br i1 %20, label %53, label %40
21: ; preds = %2
%22 = icmp eq i32 %1, 0
br i1 %22, label %69, label %23
23: ; preds = %21
%24 = add i32 %1, -1
%25 = and i32 %1, 7
%26 = icmp eq i32 %25, 0
br i1 %26, label %35, label %27
27: ; preds = %23, %27
%28 = phi double [ %32, %27 ], [ 1.000000e+00, %23 ]
%29 = phi i32 [ %31, %27 ], [ %1, %23 ]
%30 = phi i32 [ %33, %27 ], [ 0, %23 ]
%31 = add nsw i32 %29, -1
%32 = fmul double %28, %0
%33 = add i32 %30, 1
%34 = icmp eq i32 %33, %25
br i1 %34, label %35, label %27
35: ; preds = %27, %23
%36 = phi double [ undef, %23 ], [ %32, %27 ]
%37 = phi double [ 1.000000e+00, %23 ], [ %32, %27 ]
%38 = phi i32 [ %1, %23 ], [ %31, %27 ]
%39 = icmp ult i32 %24, 7
br i1 %39, label %69, label %56
40: ; preds = %16, %40
%41 = phi double [ %51, %40 ], [ %18, %16 ]
%42 = phi i32 [ %50, %40 ], [ %19, %16 ]
%43 = fmul double %41, %0
%44 = fmul double %43, %0
%45 = fmul double %44, %0
%46 = fmul double %45, %0
%47 = fmul double %46, %0
%48 = fmul double %47, %0
%49 = fmul double %48, %0
%50 = add nsw i32 %42, 8
%51 = fmul double %49, %0
%52 = icmp eq i32 %50, 0
br i1 %52, label %53, label %40
53: ; preds = %40, %16
%54 = phi double [ %17, %16 ], [ %51, %40 ]
%55 = fdiv double 1.000000e+00, %54
br label %69
56: ; preds = %35, %56
%57 = phi double [ %67, %56 ], [ %37, %35 ]
%58 = phi i32 [ %66, %56 ], [ %38, %35 ]
%59 = fmul double %57, %0
%60 = fmul double %59, %0
%61 = fmul double %60, %0
%62 = fmul double %61, %0
%63 = fmul double %62, %0
%64 = fmul double %63, %0
%65 = fmul double %64, %0
%66 = add nsw i32 %58, -8
%67 = fmul double %65, %0
%68 = icmp eq i32 %66, 0
br i1 %68, label %69, label %56
69: ; preds = %35, %56, %21, %53
%70 = phi double [ %55, %53 ], [ 1.000000e+00, %21 ], [ %36, %35 ], [ %67, %56 ]
ret double %70
}