long double my_fact(int num) {
  long double ans = 1;
  while (num > 0)
    ans *= (num--);
  return ans;
}


x86 assembly (clang, -O0):
<my_fact>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
fld1
fstpt  -0x20(%rbp)
cmpl   $0x0,-0x4(%rbp)
jle    1134 <my_fact+0x34>
mov    -0x4(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x4(%rbp)
mov    %eax,-0x24(%rbp)
fildl  -0x24(%rbp)
fldt   -0x20(%rbp)
fmulp  %st,%st(1)
fstpt  -0x20(%rbp)
jmp    110c <my_fact+0xc>
fldt   -0x20(%rbp)
pop    %rbp
ret

x86 assembly (clang, -O2):
<my_fact>:
fld1
test   %edi,%edi
fldz
jle    11b1 <my_fact+0xb1>
fstp   %st(1)
fstp   %st(0)
lea    -0x1(%rdi),%eax
mov    %edi,%ecx
fldz
fld1
and    $0x7,%ecx
je     1146 <my_fact+0x46>
fstp   %st(1)
fstp   %st(0)
fld1
fldz
fxch   %st(1)
nopl   0x0(%rax,%rax,1)
fstp   %st(1)
mov    %edi,-0x4(%rsp)
add    $0xffffffff,%edi
fimull -0x4(%rsp)
fld    %st(0)
add    $0xffffffff,%ecx
fxch   %st(1)
jne    1130 <my_fact+0x30>
cmp    $0x7,%eax
jb     11b1 <my_fact+0xb1>
fstp   %st(1)
fldz
nop
fstp   %st(0)
mov    %edi,-0x24(%rsp)
fimull -0x24(%rsp)
lea    -0x1(%rdi),%eax
mov    %eax,-0x8(%rsp)
fimull -0x8(%rsp)
lea    -0x2(%rdi),%eax
mov    %eax,-0x20(%rsp)
fimull -0x20(%rsp)
lea    -0x3(%rdi),%eax
mov    %eax,-0x1c(%rsp)
fimull -0x1c(%rsp)
lea    -0x4(%rdi),%eax
mov    %eax,-0x18(%rsp)
fimull -0x18(%rsp)
lea    -0x5(%rdi),%eax
mov    %eax,-0x14(%rsp)
fimull -0x14(%rsp)
lea    -0x6(%rdi),%eax
mov    %eax,-0x10(%rsp)
fimull -0x10(%rsp)
lea    -0x7(%rdi),%eax
mov    %eax,-0xc(%rsp)
fimull -0xc(%rsp)
add    $0xfffffff8,%edi
cmp    $0x1,%eax
fldz
ja     1150 <my_fact+0x50>
fstp   %st(0)
ret

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