unsigned __int128 factorial(int n) {
  unsigned __int128 i = 1;
  for (; n > 0; i *= n--)
    ;
  return i;
}


x86 assembly (clang, -O0):
<factorial>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x14(%rbp)
movq   $0x0,-0x28(%rbp)
movq   $0x1,-0x30(%rbp)
cmpl   $0x0,-0x14(%rbp)
jle    1170 <factorial+0x70>
jmp    1126 <factorial+0x26>
movslq -0x14(%rbp),%rsi
mov    %rsi,%rcx
sar    $0x3f,%rcx
mov    %esi,%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
mov    -0x30(%rbp),%rax
mov    -0x28(%rbp),%rdx
mov    %rdx,-0x38(%rbp)
mov    %rax,%rdi
imul   %rcx,%rdi
mul    %rsi
mov    %rax,%rcx
mov    %rdx,%rax
mov    -0x38(%rbp),%rdx
add    %rdi,%rax
imul   %rsi,%rdx
add    %rdx,%rax
mov    %rcx,-0x30(%rbp)
mov    %rax,-0x28(%rbp)
jmp    1117 <factorial+0x17>
mov    -0x30(%rbp),%rax
mov    -0x28(%rbp),%rcx
mov    %rcx,-0x8(%rbp)
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x8(%rbp),%rdx
pop    %rbp
ret

x86 assembly (clang, -O2):
<factorial>:
push   %r14
push   %rbx
test   %edi,%edi
jle    1130 <factorial+0x30>
lea    -0x1(%rdi),%r10d
mov    %edi,%r9d
and    $0x7,%r9d
xor    %r8d,%r8d
cmp    $0x7,%r10d
jae    113d <factorial+0x3d>
mov    $0x1,%eax
xor    %esi,%esi
test   %r9d,%r9d
jne    1200 <factorial+0x100>
jmp    121e <factorial+0x11e>
mov    $0x1,%eax
xor    %r8d,%r8d
jmp    121e <factorial+0x11e>
mov    %edi,%r11d
and    $0xfffffff8,%r11d
neg    %r11d
mov    $0x1,%eax
xor    %esi,%esi
xchg   %ax,%ax
lea    (%rdi,%r8,1),%ecx
lea    (%r10,%r8,1),%ebx
imul   %rcx,%rsi
mul    %rcx
mov    %rdx,%rcx
add    %rsi,%rcx
lea    (%r10,%r8,1),%esi
add    $0xffffffff,%esi
mul    %rbx
imul   %rbx,%rcx
add    %rdx,%rcx
lea    (%r10,%r8,1),%ebx
add    $0xfffffffe,%ebx
mul    %rsi
imul   %rsi,%rcx
add    %rdx,%rcx
lea    (%r10,%r8,1),%r14d
add    $0xfffffffd,%r14d
imul   %rbx,%rcx
mul    %rbx
mov    %rdx,%rsi
add    %rcx,%rsi
lea    (%r10,%r8,1),%ebx
add    $0xfffffffc,%ebx
imul   %r14,%rsi
mul    %r14
mov    %rdx,%rcx
add    %rsi,%rcx
lea    (%r10,%r8,1),%r14d
add    $0xfffffffb,%r14d
imul   %rbx,%rcx
mul    %rbx
mov    %rdx,%rsi
add    %rcx,%rsi
lea    (%r10,%r8,1),%ebx
add    $0xfffffffa,%ebx
mul    %r14
mov    %rdx,%rcx
imul   %r14,%rsi
add    %rsi,%rcx
mul    %rbx
imul   %rbx,%rcx
mov    %rdx,%rsi
add    %rcx,%rsi
add    $0xfffffff8,%r8d
cmp    %r8d,%r11d
jne    1150 <factorial+0x50>
add    %r8d,%edi
mov    %rsi,%r8
test   %r9d,%r9d
je     121e <factorial+0x11e>
xchg   %ax,%ax
mov    %edi,%ecx
add    $0xffffffff,%edi
mov    %rsi,%rbx
imul   %rcx,%rbx
mul    %rcx
mov    %rdx,%rsi
add    %rbx,%rsi
add    $0xffffffff,%r9d
jne    1200 <factorial+0x100>
mov    %rsi,%r8
mov    %r8,%rdx
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define { i64, i64 } @factorial(i32 %0) {
%2 = alloca i128
%3 = alloca i32
%4 = alloca i128
store i32 %0, i32* %3
store i128 1, i128* %4
br label %5
5: ; preds = %9, %1
%6 = load i32, i32* %3
%7 = icmp sgt i32 %6, 0
br i1 %7, label %8, label %15
8: ; preds = %5
br label %9
9: ; preds = %8
%10 = load i32, i32* %3
%11 = add nsw i32 %10, -1
store i32 %11, i32* %3
%12 = sext i32 %10 to i128
%13 = load i128, i128* %4
%14 = mul i128 %13, %12
store i128 %14, i128* %4
br label %5
15: ; preds = %5
%16 = load i128, i128* %4
store i128 %16, i128* %2
%17 = bitcast i128* %2 to { i64, i64 }*
%18 = load { i64, i64 }, { i64, i64 }* %17
ret { i64, i64 } %18
}

LLVM IR (-O2):
define { i64, i64 } @factorial(i32 %0) {
%2 = icmp sgt i32 %0, 0
br i1 %2, label %3, label %62
3: ; preds = %1
%4 = add i32 %0, -1
%5 = and i32 %0, 7
%6 = icmp ult i32 %4, 7
br i1 %6, label %43, label %7
7: ; preds = %3
%8 = and i32 %0, -8
br label %9
9: ; preds = %9, %7
%10 = phi i128 [ 1, %7 ], [ %36, %9 ]
%11 = phi i32 [ %0, %7 ], [ %34, %9 ]
%12 = phi i32 [ 0, %7 ], [ %37, %9 ]
%13 = add nsw i32 %11, -1
%14 = zext i32 %11 to i128
%15 = mul i128 %10, %14
%16 = add nsw i32 %11, -2
%17 = zext i32 %13 to i128
%18 = mul i128 %15, %17
%19 = add nsw i32 %11, -3
%20 = zext i32 %16 to i128
%21 = mul i128 %18, %20
%22 = add nsw i32 %11, -4
%23 = zext i32 %19 to i128
%24 = mul i128 %21, %23
%25 = add nsw i32 %11, -5
%26 = zext i32 %22 to i128
%27 = mul i128 %24, %26
%28 = add nsw i32 %11, -6
%29 = zext i32 %25 to i128
%30 = mul i128 %27, %29
%31 = add nsw i32 %11, -7
%32 = zext i32 %28 to i128
%33 = mul i128 %30, %32
%34 = add nsw i32 %11, -8
%35 = zext i32 %31 to i128
%36 = mul i128 %33, %35
%37 = add i32 %12, 8
%38 = icmp eq i32 %37, %8
br i1 %38, label %39, label %9
39: ; preds = %9
%40 = trunc i128 %36 to i64
%41 = lshr i128 %36, 64
%42 = trunc i128 %41 to i64
br label %43
43: ; preds = %39, %3
%44 = phi i64 [ undef, %3 ], [ %40, %39 ]
%45 = phi i64 [ 0, %3 ], [ %42, %39 ]
%46 = phi i128 [ 1, %3 ], [ %36, %39 ]
%47 = phi i32 [ %0, %3 ], [ %34, %39 ]
%48 = icmp eq i32 %5, 0
br i1 %48, label %62, label %49
49: ; preds = %43, %49
%50 = phi i128 [ %55, %49 ], [ %46, %43 ]
%51 = phi i32 [ %53, %49 ], [ %47, %43 ]
%52 = phi i32 [ %56, %49 ], [ 0, %43 ]
%53 = add nsw i32 %51, -1
%54 = zext i32 %51 to i128
%55 = mul i128 %50, %54
%56 = add i32 %52, 1
%57 = icmp eq i32 %56, %5
br i1 %57, label %58, label %49
58: ; preds = %49
%59 = trunc i128 %55 to i64
%60 = lshr i128 %55, 64
%61 = trunc i128 %60 to i64
br label %62
62: ; preds = %58, %43, %1
%63 = phi i64 [ 1, %1 ], [ %44, %43 ], [ %59, %58 ]
%64 = phi i64 [ 0, %1 ], [ %45, %43 ], [ %61, %58 ]
%65 = insertvalue { i64, i64 } poison, i64 %63, 0
%66 = insertvalue { i64, i64 } %65, i64 %64, 1
ret { i64, i64 } %66
}