int fib(int n) {
  int F[1000 + 1];
  int i;
  F[0] = 0;
  F[1] = 1;
  F[2] = 1;
  for (i = 3; i <= n; i++)
    F[i] = F[i - 2] + F[i - 1];
  return F[n];
}


x86 assembly (clang, -O0):
<fib>:
push   %rbp
mov    %rsp,%rbp
sub    $0xf40,%rsp
mov    %edi,-0x4(%rbp)
movl   $0x0,-0xfb0(%rbp)
movl   $0x1,-0xfac(%rbp)
movl   $0x1,-0xfa8(%rbp)
movl   $0x3,-0xfb4(%rbp)
mov    -0xfb4(%rbp),%eax
cmp    -0x4(%rbp),%eax
jg     118b <fib+0x8b>
mov    -0xfb4(%rbp),%eax
sub    $0x2,%eax
cltq
mov    -0xfb0(%rbp,%rax,4),%ecx
mov    -0xfb4(%rbp),%eax
sub    $0x1,%eax
cltq
add    -0xfb0(%rbp,%rax,4),%ecx
movslq -0xfb4(%rbp),%rax
mov    %ecx,-0xfb0(%rbp,%rax,4)
mov    -0xfb4(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xfb4(%rbp)
jmp    1136 <fib+0x36>
movslq -0x4(%rbp),%rax
mov    -0xfb0(%rbp,%rax,4),%eax
add    $0xf40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<fib>:
sub    $0xf28,%rsp
movabs $0x100000000,%rax
mov    %rax,-0x80(%rsp)
movl   $0x1,-0x78(%rsp)
cmp    $0x3,%edi
jl     11c5 <fib+0xc5>
mov    %edi,%eax
lea    -0x2(%rax),%r9
add    $0xfffffffffffffffd,%rax
mov    %r9d,%r8d
and    $0x3,%r8d
cmp    $0x3,%rax
jae    114f <fib+0x4f>
mov    $0x3,%eax
mov    $0x1,%edx
mov    $0x1,%ecx
jmp    119a <fib+0x9a>
and    $0xfffffffffffffffc,%r9
neg    %r9
mov    $0x3,%eax
mov    $0x1,%edx
mov    $0x1,%ecx
cs nopw 0x0(%rax,%rax,1)
nop
add    %edx,%ecx
mov    %ecx,-0x80(%rsp,%rax,4)
add    %ecx,%edx
mov    %edx,-0x7c(%rsp,%rax,4)
add    %edx,%ecx
mov    %ecx,-0x78(%rsp,%rax,4)
add    %ecx,%edx
mov    %edx,-0x74(%rsp,%rax,4)
lea    (%r9,%rax,1),%rsi
add    $0x4,%rsi
add    $0x4,%rax
cmp    $0x3,%rsi
jne    1170 <fib+0x70>
test   %r8,%r8
je     11c5 <fib+0xc5>
lea    (%rsp,%rax,4),%r9
add    $0xffffffffffffff80,%r9
xor    %esi,%esi
nopl   0x0(%rax)
mov    %edx,%eax
add    %edx,%ecx
mov    %ecx,(%r9,%rsi,4)
add    $0x1,%rsi
mov    %ecx,%edx
mov    %eax,%ecx
cmp    %rsi,%r8
jne    11b0 <fib+0xb0>
movslq %edi,%rax
mov    -0x80(%rsp,%rax,4),%eax
add    $0xf28,%rsp
ret

LLVM IR (-O0):
define i32 @fib(i32 %0) {
%2 = alloca i32
%3 = alloca [1001 x i32]
%4 = alloca i32
store i32 %0, i32* %2
%5 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 0
store i32 0, i32* %5
%6 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 1
store i32 1, i32* %6
%7 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 2
store i32 1, i32* %7
store i32 3, i32* %4
br label %8
8: ; preds = %27, %1
%9 = load i32, i32* %4
%10 = load i32, i32* %2
%11 = icmp sle i32 %9, %10
br i1 %11, label %12, label %30
12: ; preds = %8
%13 = load i32, i32* %4
%14 = sub nsw i32 %13, 2
%15 = sext i32 %14 to i64
%16 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 %15
%17 = load i32, i32* %16
%18 = load i32, i32* %4
%19 = sub nsw i32 %18, 1
%20 = sext i32 %19 to i64
%21 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 %20
%22 = load i32, i32* %21
%23 = add nsw i32 %17, %22
%24 = load i32, i32* %4
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 %25
store i32 %23, i32* %26
br label %27
27: ; preds = %12
%28 = load i32, i32* %4
%29 = add nsw i32 %28, 1
store i32 %29, i32* %4
br label %8
30: ; preds = %8
%31 = load i32, i32* %2
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds [1001 x i32], [1001 x i32]* %3, i64 0, i64 %32
%34 = load i32, i32* %33
ret i32 %34
}

LLVM IR (-O2):
define i32 @fib(i32 %0) {
%2 = alloca [1001 x i32]
%3 = bitcast [1001 x i32]* %2 to i8*
%4 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 0
store i32 0, i32* %4
%5 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 1
store i32 1, i32* %5
%6 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 2
store i32 1, i32* %6
%7 = icmp slt i32 %0, 3
br i1 %7, label %51, label %8
8: ; preds = %1
%9 = add nuw i32 %0, 1
%10 = zext i32 %9 to i64
%11 = add nsw i64 %10, -3
%12 = add nsw i64 %10, -4
%13 = and i64 %11, 3
%14 = icmp ult i64 %12, 3
br i1 %14, label %36, label %15
15: ; preds = %8
%16 = and i64 %11, -4
br label %17
17: ; preds = %17, %15
%18 = phi i32 [ 1, %15 ], [ %31, %17 ]
%19 = phi i32 [ 1, %15 ], [ %28, %17 ]
%20 = phi i64 [ 3, %15 ], [ %33, %17 ]
%21 = phi i64 [ 0, %15 ], [ %34, %17 ]
%22 = add nsw i32 %18, %19
%23 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 %20
store i32 %22, i32* %23
%24 = add nuw nsw i64 %20, 1
%25 = add nsw i32 %22, %18
%26 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 %24
store i32 %25, i32* %26
%27 = add nuw nsw i64 %20, 2
%28 = add nsw i32 %25, %22
%29 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 %27
store i32 %28, i32* %29
%30 = add nuw nsw i64 %20, 3
%31 = add nsw i32 %28, %25
%32 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 %30
store i32 %31, i32* %32
%33 = add nuw nsw i64 %20, 4
%34 = add i64 %21, 4
%35 = icmp eq i64 %34, %16
br i1 %35, label %36, label %17
36: ; preds = %17, %8
%37 = phi i32 [ 1, %8 ], [ %31, %17 ]
%38 = phi i32 [ 1, %8 ], [ %28, %17 ]
%39 = phi i64 [ 3, %8 ], [ %33, %17 ]
%40 = icmp eq i64 %13, 0
br i1 %40, label %51, label %41
41: ; preds = %36, %41
%42 = phi i32 [ %46, %41 ], [ %37, %36 ]
%43 = phi i32 [ %42, %41 ], [ %38, %36 ]
%44 = phi i64 [ %48, %41 ], [ %39, %36 ]
%45 = phi i64 [ %49, %41 ], [ 0, %36 ]
%46 = add nsw i32 %42, %43
%47 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 %44
store i32 %46, i32* %47
%48 = add nuw nsw i64 %44, 1
%49 = add i64 %45, 1
%50 = icmp eq i64 %49, %13
br i1 %50, label %51, label %41
51: ; preds = %36, %41, %1
%52 = sext i32 %0 to i64
%53 = getelementptr inbounds [1001 x i32], [1001 x i32]* %2, i64 0, i64 %52
%54 = load i32, i32* %53
ret i32 %54
}