double expon(double x, int y) {
  double t = x;
  if (y < 0)
    while (y++ <= 0)
      x /= t;
  else if (y > 0)
    while (--y >= 1)
      x *= t;
  else
    x = 1.0;
  return x;
}


x86 assembly (clang, -O0):
<expon>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
mov    %edi,-0xc(%rbp)
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
cmpl   $0x0,-0xc(%rbp)
jge    1156 <expon+0x56>
jmp    1125 <expon+0x25>
mov    -0xc(%rbp),%eax
mov    %eax,%ecx
add    $0x1,%ecx
mov    %ecx,-0xc(%rbp)
cmp    $0x0,%eax
jg     1151 <expon+0x51>
movsd  -0x18(%rbp),%xmm1
movsd  -0x8(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1125 <expon+0x25>
jmp    11a2 <expon+0xa2>
cmpl   $0x0,-0xc(%rbp)
jle    1190 <expon+0x90>
jmp    1165 <expon+0x65>
mov    -0xc(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0xc(%rbp)
cmp    $0x1,%eax
jl     118b <expon+0x8b>
movsd  -0x18(%rbp),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1165 <expon+0x65>
jmp    119d <expon+0x9d>
movsd  0xe68(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11a2 <expon+0xa2>
movsd  -0x8(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<expon>:
test   %edi,%edi
js     1114 <expon+0x14>
je     1141 <expon+0x41>
cmp    $0x1,%edi
jne    114a <expon+0x4a>
movapd %xmm0,%xmm1
jmp    1195 <expon+0x95>
mov    $0x1,%eax
sub    %edi,%eax
and    $0x3,%eax
je     116e <expon+0x6e>
neg    %eax
xor    %ecx,%ecx
movapd %xmm0,%xmm1
nopl   0x0(%rax,%rax,1)
divsd  %xmm0,%xmm1
add    $0xffffffff,%ecx
cmp    %ecx,%eax
jne    1130 <expon+0x30>
mov    %edi,%eax
sub    %ecx,%eax
jmp    1174 <expon+0x74>
movsd  0xeb7(%rip),%xmm0
ret
add    $0x1,%edi
movapd %xmm0,%xmm1
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mulsd  %xmm0,%xmm1
add    $0xffffffff,%edi
cmp    $0x2,%edi
ja     1160 <expon+0x60>
jmp    1195 <expon+0x95>
movapd %xmm0,%xmm1
mov    %edi,%eax
add    $0x2,%edi
cmp    $0x3,%edi
jb     1195 <expon+0x95>
add    $0xffffffff,%eax
nop
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
add    $0x4,%eax
jne    1180 <expon+0x80>
movapd %xmm1,%xmm0
ret

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

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