long calculateSum(int a[], int n) {
  static long sum = 0;
  if (n == 0)
    return sum;
  sum = sum + a[n - 1];
  return calculateSum(a, --n);
}


x86 assembly (clang, -O0):
<calculateSum>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jne    1139 <calculateSum+0x29>
mov    0x2f00(%rip),%rax
mov    %rax,-0x8(%rbp)
jmp    1171 <calculateSum+0x61>
mov    0x2ef0(%rip),%rax
mov    -0x10(%rbp),%rcx
mov    -0x14(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
movslq (%rcx,%rdx,4),%rcx
add    %rcx,%rax
mov    %rax,0x2ed5(%rip)
mov    -0x10(%rbp),%rdi
mov    -0x14(%rbp),%esi
add    $0xffffffff,%esi
mov    %esi,-0x14(%rbp)
call   1030 <calculateSum@plt>
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<calculateSum>:
mov    0x2f21(%rip),%rax
test   %esi,%esi
je     1257 <calculateSum+0x157>
movslq %esi,%rcx
add    $0xffffffff,%esi
cmp    $0x3,%esi
jb     1240 <calculateSum+0x140>
add    $0x1,%rsi
mov    %rsi,%r8
and    $0xfffffffffffffffc,%r8
movq   %rax,%xmm0
lea    -0x4(%r8),%rax
mov    %rax,%r9
shr    $0x2,%r9
add    $0x1,%r9
test   %rax,%rax
je     1258 <calculateSum+0x158>
mov    %r9,%rax
and    $0xfffffffffffffffe,%rax
lea    (%rdi,%rcx,4),%r10
add    $0xfffffffffffffff8,%r10
pxor   %xmm1,%xmm1
mov    $0xfffffffffffffffe,%rdx
movq   0x8(%r10,%rdx,4),%xmm2
pshufd $0xe1,%xmm2,%xmm2
movq   (%r10,%rdx,4),%xmm3
pshufd $0xe1,%xmm3,%xmm3
pxor   %xmm4,%xmm4
pcmpgtd %xmm2,%xmm4
punpckldq %xmm4,%xmm2
paddq  %xmm0,%xmm2
pxor   %xmm0,%xmm0
pcmpgtd %xmm3,%xmm0
punpckldq %xmm0,%xmm3
paddq  %xmm1,%xmm3
movq   -0x8(%r10,%rdx,4),%xmm0
pshufd $0xe1,%xmm0,%xmm0
movq   -0x10(%r10,%rdx,4),%xmm1
pshufd $0xe1,%xmm1,%xmm1
pxor   %xmm4,%xmm4
pcmpgtd %xmm0,%xmm4
punpckldq %xmm4,%xmm0
paddq  %xmm2,%xmm0
pxor   %xmm2,%xmm2
pcmpgtd %xmm1,%xmm2
punpckldq %xmm2,%xmm1
paddq  %xmm3,%xmm1
add    $0xfffffffffffffff8,%rdx
add    $0xfffffffffffffffe,%rax
jne    1160 <calculateSum+0x60>
add    $0x1,%rdx
test   $0x1,%r9b
je     121c <calculateSum+0x11c>
add    %rcx,%rdx
movq   -0x4(%rdi,%rdx,4),%xmm2
pshufd $0xe1,%xmm2,%xmm2
movq   -0xc(%rdi,%rdx,4),%xmm3
pshufd $0xe1,%xmm3,%xmm3
pxor   %xmm4,%xmm4
pxor   %xmm5,%xmm5
pcmpgtd %xmm2,%xmm5
punpckldq %xmm5,%xmm2
paddq  %xmm2,%xmm0
pcmpgtd %xmm3,%xmm4
punpckldq %xmm4,%xmm3
paddq  %xmm3,%xmm1
paddq  %xmm1,%xmm0
pshufd $0xee,%xmm0,%xmm1
paddq  %xmm0,%xmm1
movq   %xmm1,%rax
cmp    %r8,%rsi
je     1250 <calculateSum+0x150>
sub    %r8,%rcx
cs nopw 0x0(%rax,%rax,1)
movslq -0x4(%rdi,%rcx,4),%rdx
add    $0xffffffffffffffff,%rcx
add    %rdx,%rax
test   %ecx,%ecx
jne    1240 <calculateSum+0x140>
mov    %rax,0x2dd1(%rip)
ret
pxor   %xmm1,%xmm1
mov    $0xffffffffffffffff,%rdx
test   $0x1,%r9b
jne    11e3 <calculateSum+0xe3>
jmp    121c <calculateSum+0x11c>

LLVM IR (-O0):
@calculateSum.sum = internal global i64 0
define i64 @calculateSum(i32* %0, i32 %1) {
%3 = alloca i64
%4 = alloca i32*
%5 = alloca i32
store i32* %0, i32** %4
store i32 %1, i32* %5
%6 = load i32, i32* %5
%7 = icmp eq i32 %6, 0
br i1 %7, label %8, label %10
8: ; preds = %2
%9 = load i64, i64* @calculateSum.sum
store i64 %9, i64* %3
br label %24
10: ; preds = %2
%11 = load i64, i64* @calculateSum.sum
%12 = load i32*, i32** %4
%13 = load i32, i32* %5
%14 = sub nsw i32 %13, 1
%15 = sext i32 %14 to i64
%16 = getelementptr inbounds i32, i32* %12, i64 %15
%17 = load i32, i32* %16
%18 = sext i32 %17 to i64
%19 = add nsw i64 %11, %18
store i64 %19, i64* @calculateSum.sum
%20 = load i32*, i32** %4
%21 = load i32, i32* %5
%22 = add nsw i32 %21, -1
store i32 %22, i32* %5
%23 = call i64 @calculateSum(i32* %20, i32 %22)
store i64 %23, i64* %3
br label %24
24: ; preds = %10, %8
%25 = load i64, i64* %3
ret i64 %25
}

LLVM IR (-O2):
@calculateSum.sum = internal unnamed_addr global i64 0
define i64 @calculateSum(i32* nocapture %0, i32 %1) {
%3 = load i64, i64* @calculateSum.sum
%4 = icmp eq i32 %1, 0
br i1 %4, label %98, label %5
5: ; preds = %2
%6 = sext i32 %1 to i64
%7 = add i32 %1, -1
%8 = zext i32 %7 to i64
%9 = add nuw nsw i64 %8, 1
%10 = icmp ult i32 %7, 3
br i1 %10, label %93, label %11
11: ; preds = %5
%12 = and i64 %9, 8589934588
%13 = sub nsw i64 %6, %12
%14 = insertelement <2 x i64> <i64 poison, i64 0>, i64 %3, i64 0
%15 = add nsw i64 %12, -4
%16 = lshr exact i64 %15, 2
%17 = add nuw nsw i64 %16, 1
%18 = and i64 %17, 1
%19 = icmp eq i64 %15, 0
br i1 %19, label %64, label %20
20: ; preds = %11
%21 = and i64 %17, 9223372036854775806
br label %22
22: ; preds = %22, %20
%23 = phi i64 [ 0, %20 ], [ %59, %22 ]
%24 = phi <2 x i64> [ %14, %20 ], [ %57, %22 ]
%25 = phi <2 x i64> [ zeroinitializer, %20 ], [ %58, %22 ]
%26 = phi i64 [ 0, %20 ], [ %60, %22 ]
%27 = xor i64 %23, -1
%28 = add i64 %27, %6
%29 = getelementptr inbounds i32, i32* %0, i64 %28
%30 = getelementptr inbounds i32, i32* %29, i64 -1
%31 = bitcast i32* %30 to <2 x i32>*
%32 = load <2 x i32>, <2 x i32>* %31
%33 = shufflevector <2 x i32> %32, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
%34 = getelementptr inbounds i32, i32* %29, i64 -2
%35 = getelementptr inbounds i32, i32* %34, i64 -1
%36 = bitcast i32* %35 to <2 x i32>*
%37 = load <2 x i32>, <2 x i32>* %36
%38 = shufflevector <2 x i32> %37, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
%39 = sext <2 x i32> %33 to <2 x i64>
%40 = sext <2 x i32> %38 to <2 x i64>
%41 = add <2 x i64> %24, %39
%42 = add <2 x i64> %25, %40
%43 = sub nuw nsw i64 -5, %23
%44 = add i64 %43, %6
%45 = getelementptr inbounds i32, i32* %0, i64 %44
%46 = getelementptr inbounds i32, i32* %45, i64 -1
%47 = bitcast i32* %46 to <2 x i32>*
%48 = load <2 x i32>, <2 x i32>* %47
%49 = shufflevector <2 x i32> %48, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
%50 = getelementptr inbounds i32, i32* %45, i64 -2
%51 = getelementptr inbounds i32, i32* %50, i64 -1
%52 = bitcast i32* %51 to <2 x i32>*
%53 = load <2 x i32>, <2 x i32>* %52
%54 = shufflevector <2 x i32> %53, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
%55 = sext <2 x i32> %49 to <2 x i64>
%56 = sext <2 x i32> %54 to <2 x i64>
%57 = add <2 x i64> %41, %55
%58 = add <2 x i64> %42, %56
%59 = add nuw i64 %23, 8
%60 = add i64 %26, 2
%61 = icmp eq i64 %60, %21
br i1 %61, label %62, label %22
62: ; preds = %22
%63 = sub i64 -9, %23
br label %64
64: ; preds = %62, %11
%65 = phi <2 x i64> [ undef, %11 ], [ %57, %62 ]
%66 = phi <2 x i64> [ undef, %11 ], [ %58, %62 ]
%67 = phi i64 [ -1, %11 ], [ %63, %62 ]
%68 = phi <2 x i64> [ %14, %11 ], [ %57, %62 ]
%69 = phi <2 x i64> [ zeroinitializer, %11 ], [ %58, %62 ]
%70 = icmp eq i64 %18, 0
br i1 %70, label %87, label %71
71: ; preds = %64
%72 = add i64 %67, %6
%73 = getelementptr inbounds i32, i32* %0, i64 %72
%74 = getelementptr inbounds i32, i32* %73, i64 -1
%75 = bitcast i32* %74 to <2 x i32>*
%76 = load <2 x i32>, <2 x i32>* %75
%77 = shufflevector <2 x i32> %76, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
%78 = getelementptr inbounds i32, i32* %73, i64 -2
%79 = getelementptr inbounds i32, i32* %78, i64 -1
%80 = bitcast i32* %79 to <2 x i32>*
%81 = load <2 x i32>, <2 x i32>* %80
%82 = shufflevector <2 x i32> %81, <2 x i32> poison, <2 x i32> <i32 1, i32 0>
%83 = sext <2 x i32> %77 to <2 x i64>
%84 = sext <2 x i32> %82 to <2 x i64>
%85 = add <2 x i64> %68, %83
%86 = add <2 x i64> %69, %84
br label %87
87: ; preds = %64, %71
%88 = phi <2 x i64> [ %65, %64 ], [ %85, %71 ]
%89 = phi <2 x i64> [ %66, %64 ], [ %86, %71 ]
%90 = add <2 x i64> %89, %88
%91 = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %90)
%92 = icmp eq i64 %9, %12
br i1 %92, label %96, label %93
93: ; preds = %5, %87
%94 = phi i64 [ %6, %5 ], [ %13, %87 ]
%95 = phi i64 [ %3, %5 ], [ %91, %87 ]
br label %100
96: ; preds = %100, %87
%97 = phi i64 [ %91, %87 ], [ %107, %100 ]
store i64 %97, i64* @calculateSum.sum
br label %98
98: ; preds = %96, %2
%99 = phi i64 [ %97, %96 ], [ %3, %2 ]
ret i64 %99
100: ; preds = %93, %100
%101 = phi i64 [ %103, %100 ], [ %94, %93 ]
%102 = phi i64 [ %107, %100 ], [ %95, %93 ]
%103 = add nsw i64 %101, -1
%104 = getelementptr inbounds i32, i32* %0, i64 %103
%105 = load i32, i32* %104
%106 = sext i32 %105 to i64
%107 = add nsw i64 %102, %106
%108 = trunc i64 %103 to i32
%109 = icmp eq i32 %108, 0
br i1 %109, label %96, label %100
}