long double factorial(register unsigned int n) {
  long double f = 1;
  while (n > 1) {
    f *= n--;
  }
  return f;
}


x86 assembly (clang, -O0):
<factorial>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
fld1
fstpt  -0x20(%rbp)
cmpl   $0x1,-0x4(%rbp)
jbe    1135 <factorial+0x35>
mov    -0x4(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x4(%rbp)
mov    %rax,-0x28(%rbp)
fildll -0x28(%rbp)
fldt   -0x20(%rbp)
fmulp  %st,%st(1)
fstpt  -0x20(%rbp)
jmp    110c <factorial+0xc>
fldt   -0x20(%rbp)
pop    %rbp
ret

x86 assembly (clang, -O2):
<factorial>:
fld1
cmp    $0x2,%edi
fldz
jb     11db <factorial+0xdb>
fstp   %st(1)
fstp   %st(0)
lea    -0x1(%rdi),%ecx
lea    -0x2(%rdi),%eax
fldz
fld1
and    $0x7,%ecx
je     114b <factorial+0x4b>
fstp   %st(1)
fstp   %st(0)
fld1
fldz
fxch   %st(1)
nopw   0x0(%rax,%rax,1)
fstp   %st(1)
mov    %edi,%edx
add    $0xffffffff,%edi
mov    %rdx,-0x8(%rsp)
fildll -0x8(%rsp)
fmulp  %st,%st(1)
fld    %st(0)
add    $0xffffffff,%ecx
fxch   %st(1)
jne    1130 <factorial+0x30>
cmp    $0x7,%eax
jb     11db <factorial+0xdb>
fstp   %st(1)
fldz
nopl   0x0(%rax,%rax,1)
fstp   %st(0)
lea    -0x1(%rdi),%eax
mov    %edi,%ecx
mov    %rcx,-0x10(%rsp)
fildll -0x10(%rsp)
fmulp  %st,%st(1)
mov    %rax,-0x48(%rsp)
fildll -0x48(%rsp)
fmulp  %st,%st(1)
lea    -0x2(%rdi),%eax
mov    %rax,-0x18(%rsp)
fildll -0x18(%rsp)
fmulp  %st,%st(1)
lea    -0x3(%rdi),%eax
mov    %rax,-0x20(%rsp)
fildll -0x20(%rsp)
fmulp  %st,%st(1)
lea    -0x4(%rdi),%eax
mov    %rax,-0x28(%rsp)
fildll -0x28(%rsp)
fmulp  %st,%st(1)
lea    -0x5(%rdi),%eax
mov    %rax,-0x30(%rsp)
fildll -0x30(%rsp)
fmulp  %st,%st(1)
lea    -0x6(%rdi),%eax
mov    %rax,-0x38(%rsp)
fildll -0x38(%rsp)
fmulp  %st,%st(1)
lea    -0x7(%rdi),%eax
mov    %rax,-0x40(%rsp)
fildll -0x40(%rsp)
fmulp  %st,%st(1)
add    $0xfffffff8,%edi
cmp    $0x1,%edi
fldz
ja     1160 <factorial+0x60>
fstp   %st(0)
ret

LLVM IR (-O0):
define x86_fp80 @factorial(i32 %0) {
%2 = alloca i32
%3 = alloca x86_fp80
store i32 %0, i32* %2
store x86_fp80 0xK3FFF8000000000000000, x86_fp80* %3
br label %4
4: ; preds = %7, %1
%5 = load i32, i32* %2
%6 = icmp ugt i32 %5, 1
br i1 %6, label %7, label %13
7: ; preds = %4
%8 = load i32, i32* %2
%9 = add i32 %8, -1
store i32 %9, i32* %2
%10 = uitofp i32 %8 to x86_fp80
%11 = load x86_fp80, x86_fp80* %3
%12 = fmul x86_fp80 %11, %10
store x86_fp80 %12, x86_fp80* %3
br label %4
13: ; preds = %4
%14 = load x86_fp80, x86_fp80* %3
ret x86_fp80 %14
}

LLVM IR (-O2):
define x86_fp80 @factorial(i32 %0) {
%2 = icmp ugt i32 %0, 1
br i1 %2, label %3, label %50
3: ; preds = %1
%4 = add i32 %0, 7
%5 = add i32 %0, -2
%6 = and i32 %4, 7
%7 = icmp eq i32 %6, 0
br i1 %7, label %17, label %8
8: ; preds = %3, %8
%9 = phi x86_fp80 [ %14, %8 ], [ 0xK3FFF8000000000000000, %3 ]
%10 = phi i32 [ %12, %8 ], [ %0, %3 ]
%11 = phi i32 [ %15, %8 ], [ 0, %3 ]
%12 = add i32 %10, -1
%13 = uitofp i32 %10 to x86_fp80
%14 = fmul x86_fp80 %9, %13
%15 = add i32 %11, 1
%16 = icmp eq i32 %15, %6
br i1 %16, label %17, label %8
17: ; preds = %8, %3
%18 = phi x86_fp80 [ 0xK3FFF8000000000000000, %3 ], [ %14, %8 ]
%19 = phi i32 [ %0, %3 ], [ %12, %8 ]
%20 = phi x86_fp80 [ undef, %3 ], [ %14, %8 ]
%21 = icmp ult i32 %5, 7
br i1 %21, label %50, label %22
22: ; preds = %17, %22
%23 = phi x86_fp80 [ %48, %22 ], [ %18, %17 ]
%24 = phi i32 [ %46, %22 ], [ %19, %17 ]
%25 = add i32 %24, -1
%26 = uitofp i32 %24 to x86_fp80
%27 = fmul x86_fp80 %23, %26
%28 = add i32 %24, -2
%29 = uitofp i32 %25 to x86_fp80
%30 = fmul x86_fp80 %27, %29
%31 = add i32 %24, -3
%32 = uitofp i32 %28 to x86_fp80
%33 = fmul x86_fp80 %30, %32
%34 = add i32 %24, -4
%35 = uitofp i32 %31 to x86_fp80
%36 = fmul x86_fp80 %33, %35
%37 = add i32 %24, -5
%38 = uitofp i32 %34 to x86_fp80
%39 = fmul x86_fp80 %36, %38
%40 = add i32 %24, -6
%41 = uitofp i32 %37 to x86_fp80
%42 = fmul x86_fp80 %39, %41
%43 = add i32 %24, -7
%44 = uitofp i32 %40 to x86_fp80
%45 = fmul x86_fp80 %42, %44
%46 = add i32 %24, -8
%47 = uitofp i32 %43 to x86_fp80
%48 = fmul x86_fp80 %45, %47
%49 = icmp ugt i32 %46, 1
br i1 %49, label %22, label %50
50: ; preds = %17, %22, %1
%51 = phi x86_fp80 [ 0xK3FFF8000000000000000, %1 ], [ %20, %17 ], [ %48, %22 ]
ret x86_fp80 %51
}