double foo(int N) {
  int i;
  double u[N], v[N], vBv, vv;
  for (i = 0; i < N; i++) {
    u[i] = 3;
    v[i] = 2;
  }
  vBv = vv = 0;
  for (i = 0; i < N; i++) {
    vBv += u[i] * v[i];
  }
  return (vBv);
}


x86 assembly (clang, -O0):
<foo>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %edi,-0x4(%rbp)
mov    -0x4(%rbp),%eax
mov    %rsp,%rcx
mov    %rcx,-0x10(%rbp)
lea    0xf(,%rax,8),%rdx
and    $0xfffffffffffffff0,%rdx
mov    %rsp,%rcx
sub    %rdx,%rcx
mov    %rcx,-0x40(%rbp)
mov    %rcx,%rsp
mov    %rax,-0x18(%rbp)
mov    -0x4(%rbp),%eax
lea    0xf(,%rax,8),%rdx
and    $0xfffffffffffffff0,%rdx
mov    %rsp,%rcx
sub    %rdx,%rcx
mov    %rcx,-0x38(%rbp)
mov    %rcx,%rsp
mov    %rax,-0x20(%rbp)
movl   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    119d <foo+0x9d>
mov    -0x38(%rbp),%rax
mov    -0x40(%rbp),%rcx
movslq -0x8(%rbp),%rdx
movsd  0xe8f(%rip),%xmm0
movsd  %xmm0,(%rcx,%rdx,8)
movslq -0x8(%rbp),%rcx
movsd  0xe76(%rip),%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    1159 <foo+0x59>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x30(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x28(%rbp)
movl   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    11fa <foo+0xfa>
mov    -0x38(%rbp),%rax
mov    -0x40(%rbp),%rcx
movslq -0x8(%rbp),%rdx
movsd  (%rcx,%rdx,8),%xmm0
movslq -0x8(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    11b4 <foo+0xb4>
movsd  -0x28(%rbp),%xmm0
mov    -0x10(%rbp),%rax
mov    %rax,%rsp
mov    %rbp,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<foo>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,%r9d
mov    %rsp,%r10
lea    0xf(,%r9,8),%rax
and    $0xfffffffffffffff0,%rax
sub    %rax,%r10
mov    %r10,%rsp
mov    %rsp,%rcx
sub    %rax,%rcx
mov    %rcx,%rsp
xorpd  %xmm0,%xmm0
test   %edi,%edi
jle    1317 <foo+0x217>
cmp    $0x4,%edi
jae    113d <foo+0x3d>
xor    %esi,%esi
jmp    1246 <foo+0x146>
mov    %r9d,%esi
and    $0xfffffffc,%esi
lea    -0x4(%rsi),%rax
mov    %rax,%rdx
shr    $0x2,%rdx
add    $0x1,%rdx
mov    %edx,%r8d
and    $0x3,%r8d
cmp    $0xc,%rax
jae    1166 <foo+0x66>
xor    %eax,%eax
jmp    11f0 <foo+0xf0>
and    $0xfffffffffffffffc,%rdx
xor    %eax,%eax
movapd 0xe8c(%rip),%xmm1
movapd 0xe94(%rip),%xmm2
nopl   0x0(%rax)
movapd %xmm1,(%r10,%rax,8)
movapd %xmm1,0x10(%r10,%rax,8)
movapd %xmm2,(%rcx,%rax,8)
movapd %xmm2,0x10(%rcx,%rax,8)
movapd %xmm1,0x20(%r10,%rax,8)
movapd %xmm1,0x30(%r10,%rax,8)
movapd %xmm2,0x20(%rcx,%rax,8)
movapd %xmm2,0x30(%rcx,%rax,8)
movapd %xmm1,0x40(%r10,%rax,8)
movapd %xmm1,0x50(%r10,%rax,8)
movapd %xmm2,0x40(%rcx,%rax,8)
movapd %xmm2,0x50(%rcx,%rax,8)
movapd %xmm1,0x60(%r10,%rax,8)
movapd %xmm1,0x70(%r10,%rax,8)
movapd %xmm2,0x60(%rcx,%rax,8)
movapd %xmm2,0x70(%rcx,%rax,8)
add    $0x10,%rax
add    $0xfffffffffffffffc,%rdx
jne    1180 <foo+0x80>
test   %r8,%r8
je     1241 <foo+0x141>
lea    (%rcx,%rax,8),%r11
add    $0x10,%r11
lea    (%r10,%rax,8),%rax
add    $0x10,%rax
shl    $0x5,%r8
xor    %edx,%edx
movapd 0xded(%rip),%xmm1
movapd 0xdf5(%rip),%xmm2
nopl   0x0(%rax,%rax,1)
movapd %xmm1,-0x10(%rax,%rdx,1)
movapd %xmm1,(%rax,%rdx,1)
movapd %xmm2,-0x10(%r11,%rdx,1)
movapd %xmm2,(%r11,%rdx,1)
add    $0x20,%rdx
cmp    %rdx,%r8
jne    1220 <foo+0x120>
cmp    %r9,%rsi
je     1271 <foo+0x171>
movabs $0x4008000000000000,%rax
movabs $0x4000000000000000,%rdx
nopw   0x0(%rax,%rax,1)
mov    %rax,(%r10,%rsi,8)
mov    %rdx,(%rcx,%rsi,8)
add    $0x1,%rsi
cmp    %rsi,%r9
jne    1260 <foo+0x160>
test   %edi,%edi
jle    1317 <foo+0x217>
lea    -0x1(%r9),%rax
mov    %r9d,%esi
and    $0x3,%esi
cmp    $0x3,%rax
jae    1291 <foo+0x191>
xorpd  %xmm0,%xmm0
xor    %edi,%edi
jmp    12eb <foo+0x1eb>
and    $0xfffffffc,%r9d
xorpd  %xmm0,%xmm0
xor    %edi,%edi
nopl   0x0(%rax,%rax,1)
movsd  (%r10,%rdi,8),%xmm1
movsd  0x8(%r10,%rdi,8),%xmm2
mulsd  (%rcx,%rdi,8),%xmm1
mulsd  0x8(%rcx,%rdi,8),%xmm2
addsd  %xmm0,%xmm1
movsd  0x10(%r10,%rdi,8),%xmm3
mulsd  0x10(%rcx,%rdi,8),%xmm3
addsd  %xmm1,%xmm2
movsd  0x18(%r10,%rdi,8),%xmm0
mulsd  0x18(%rcx,%rdi,8),%xmm0
addsd  %xmm2,%xmm3
addsd  %xmm3,%xmm0
add    $0x4,%rdi
cmp    %rdi,%r9
jne    12a0 <foo+0x1a0>
test   %rsi,%rsi
je     1317 <foo+0x217>
lea    (%rcx,%rdi,8),%rax
lea    (%r10,%rdi,8),%rcx
xor    %edx,%edx
nopw   0x0(%rax,%rax,1)
movsd  (%rcx,%rdx,8),%xmm1
mulsd  (%rax,%rdx,8),%xmm1
addsd  %xmm1,%xmm0
add    $0x1,%rdx
cmp    %rdx,%rsi
jne    1300 <foo+0x200>
mov    %rbp,%rsp
pop    %rbp
ret

LLVM IR (-O0):
define double @foo(i32 %0) {
%2 = alloca i32
%3 = alloca i32
%4 = alloca i8*
%5 = alloca i64
%6 = alloca i64
%7 = alloca double
%8 = alloca double
store i32 %0, i32* %2
%9 = load i32, i32* %2
%10 = zext i32 %9 to i64
%11 = call i8* @llvm.stacksave()
store i8* %11, i8** %4
%12 = alloca double, i64 %10
store i64 %10, i64* %5
%13 = load i32, i32* %2
%14 = zext i32 %13 to i64
%15 = alloca double, i64 %14
store i64 %14, i64* %6
store i32 0, i32* %3
br label %16
16: ; preds = %27, %1
%17 = load i32, i32* %3
%18 = load i32, i32* %2
%19 = icmp slt i32 %17, %18
br i1 %19, label %20, label %30
20: ; preds = %16
%21 = load i32, i32* %3
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds double, double* %12, i64 %22
store double 3.000000e+00, double* %23
%24 = load i32, i32* %3
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds double, double* %15, i64 %25
store double 2.000000e+00, double* %26
br label %27
27: ; preds = %20
%28 = load i32, i32* %3
%29 = add nsw i32 %28, 1
store i32 %29, i32* %3
br label %16
30: ; preds = %16
store double 0.000000e+00, double* %8
store double 0.000000e+00, double* %7
store i32 0, i32* %3
br label %31
31: ; preds = %46, %30
%32 = load i32, i32* %3
%33 = load i32, i32* %2
%34 = icmp slt i32 %32, %33
br i1 %34, label %35, label %49
35: ; preds = %31
%36 = load i32, i32* %3
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds double, double* %12, i64 %37
%39 = load double, double* %38
%40 = load i32, i32* %3
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds double, double* %15, i64 %41
%43 = load double, double* %42
%44 = load double, double* %7
%45 = call double @llvm.fmuladd.f64(double %39, double %43, double %44)
store double %45, double* %7
br label %46
46: ; preds = %35
%47 = load i32, i32* %3
%48 = add nsw i32 %47, 1
store i32 %48, i32* %3
br label %31
49: ; preds = %31
%50 = load double, double* %7
%51 = load i8*, i8** %4
ret double %50
}

LLVM IR (-O2):
define double @foo(i32 %0) {
%2 = zext i32 %0 to i64
%3 = alloca double, i64 %2
%4 = alloca double, i64 %2
%5 = icmp sgt i32 %0, 0
br i1 %5, label %6, label %139
6: ; preds = %1
%7 = icmp ult i32 %0, 4
br i1 %7, label %77, label %8
8: ; preds = %6
%9 = and i64 %2, 4294967292
%10 = add nsw i64 %9, -4
%11 = lshr exact i64 %10, 2
%12 = add nuw nsw i64 %11, 1
%13 = and i64 %12, 3
%14 = icmp ult i64 %10, 12
br i1 %14, label %58, label %15
15: ; preds = %8
%16 = and i64 %12, 9223372036854775804
br label %17
17: ; preds = %17, %15
%18 = phi i64 [ 0, %15 ], [ %55, %17 ]
%19 = phi i64 [ 0, %15 ], [ %56, %17 ]
%20 = getelementptr inbounds double, double* %3, i64 %18
%21 = bitcast double* %20 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %21
%22 = getelementptr inbounds double, double* %20, i64 2
%23 = bitcast double* %22 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %23
%24 = getelementptr inbounds double, double* %4, i64 %18
%25 = bitcast double* %24 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %25
%26 = getelementptr inbounds double, double* %24, i64 2
%27 = bitcast double* %26 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %27
%28 = or i64 %18, 4
%29 = getelementptr inbounds double, double* %3, i64 %28
%30 = bitcast double* %29 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %30
%31 = getelementptr inbounds double, double* %29, i64 2
%32 = bitcast double* %31 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %32
%33 = getelementptr inbounds double, double* %4, i64 %28
%34 = bitcast double* %33 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %34
%35 = getelementptr inbounds double, double* %33, i64 2
%36 = bitcast double* %35 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %36
%37 = or i64 %18, 8
%38 = getelementptr inbounds double, double* %3, i64 %37
%39 = bitcast double* %38 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %39
%40 = getelementptr inbounds double, double* %38, i64 2
%41 = bitcast double* %40 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %41
%42 = getelementptr inbounds double, double* %4, i64 %37
%43 = bitcast double* %42 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %43
%44 = getelementptr inbounds double, double* %42, i64 2
%45 = bitcast double* %44 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %45
%46 = or i64 %18, 12
%47 = getelementptr inbounds double, double* %3, i64 %46
%48 = bitcast double* %47 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %48
%49 = getelementptr inbounds double, double* %47, i64 2
%50 = bitcast double* %49 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %50
%51 = getelementptr inbounds double, double* %4, i64 %46
%52 = bitcast double* %51 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %52
%53 = getelementptr inbounds double, double* %51, i64 2
%54 = bitcast double* %53 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %54
%55 = add nuw i64 %18, 16
%56 = add nuw i64 %19, 4
%57 = icmp eq i64 %56, %16
br i1 %57, label %58, label %17
58: ; preds = %17, %8
%59 = phi i64 [ 0, %8 ], [ %55, %17 ]
%60 = icmp eq i64 %13, 0
br i1 %60, label %75, label %61
61: ; preds = %58, %61
%62 = phi i64 [ %72, %61 ], [ %59, %58 ]
%63 = phi i64 [ %73, %61 ], [ 0, %58 ]
%64 = getelementptr inbounds double, double* %3, i64 %62
%65 = bitcast double* %64 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %65
%66 = getelementptr inbounds double, double* %64, i64 2
%67 = bitcast double* %66 to <2 x double>*
store <2 x double> <double 3.000000e+00, double 3.000000e+00>, <2 x double>* %67
%68 = getelementptr inbounds double, double* %4, i64 %62
%69 = bitcast double* %68 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %69
%70 = getelementptr inbounds double, double* %68, i64 2
%71 = bitcast double* %70 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %71
%72 = add nuw i64 %62, 4
%73 = add i64 %63, 1
%74 = icmp eq i64 %73, %13
br i1 %74, label %75, label %61
75: ; preds = %61, %58
%76 = icmp eq i64 %9, %2
br i1 %76, label %79, label %77
77: ; preds = %6, %75
%78 = phi i64 [ 0, %6 ], [ %9, %75 ]
br label %86
79: ; preds = %86, %75
br i1 %5, label %80, label %139
80: ; preds = %79
%81 = add nsw i64 %2, -1
%82 = and i64 %2, 3
%83 = icmp ult i64 %81, 3
br i1 %83, label %122, label %84
84: ; preds = %80
%85 = and i64 %2, 4294967292
br label %92
86: ; preds = %77, %86
%87 = phi i64 [ %90, %86 ], [ %78, %77 ]
%88 = getelementptr inbounds double, double* %3, i64 %87
store double 3.000000e+00, double* %88
%89 = getelementptr inbounds double, double* %4, i64 %87
store double 2.000000e+00, double* %89
%90 = add nuw nsw i64 %87, 1
%91 = icmp eq i64 %90, %2
br i1 %91, label %79, label %86
92: ; preds = %92, %84
%93 = phi i64 [ 0, %84 ], [ %119, %92 ]
%94 = phi double [ 0.000000e+00, %84 ], [ %118, %92 ]
%95 = phi i64 [ 0, %84 ], [ %120, %92 ]
%96 = getelementptr inbounds double, double* %3, i64 %93
%97 = load double, double* %96
%98 = getelementptr inbounds double, double* %4, i64 %93
%99 = load double, double* %98
%100 = tail call double @llvm.fmuladd.f64(double %97, double %99, double %94)
%101 = or i64 %93, 1
%102 = getelementptr inbounds double, double* %3, i64 %101
%103 = load double, double* %102
%104 = getelementptr inbounds double, double* %4, i64 %101
%105 = load double, double* %104
%106 = tail call double @llvm.fmuladd.f64(double %103, double %105, double %100)
%107 = or i64 %93, 2
%108 = getelementptr inbounds double, double* %3, i64 %107
%109 = load double, double* %108
%110 = getelementptr inbounds double, double* %4, i64 %107
%111 = load double, double* %110
%112 = tail call double @llvm.fmuladd.f64(double %109, double %111, double %106)
%113 = or i64 %93, 3
%114 = getelementptr inbounds double, double* %3, i64 %113
%115 = load double, double* %114
%116 = getelementptr inbounds double, double* %4, i64 %113
%117 = load double, double* %116
%118 = tail call double @llvm.fmuladd.f64(double %115, double %117, double %112)
%119 = add nuw nsw i64 %93, 4
%120 = add i64 %95, 4
%121 = icmp eq i64 %120, %85
br i1 %121, label %122, label %92
122: ; preds = %92, %80
%123 = phi double [ undef, %80 ], [ %118, %92 ]
%124 = phi i64 [ 0, %80 ], [ %119, %92 ]
%125 = phi double [ 0.000000e+00, %80 ], [ %118, %92 ]
%126 = icmp eq i64 %82, 0
br i1 %126, label %139, label %127
127: ; preds = %122, %127
%128 = phi i64 [ %136, %127 ], [ %124, %122 ]
%129 = phi double [ %135, %127 ], [ %125, %122 ]
%130 = phi i64 [ %137, %127 ], [ 0, %122 ]
%131 = getelementptr inbounds double, double* %3, i64 %128
%132 = load double, double* %131
%133 = getelementptr inbounds double, double* %4, i64 %128
%134 = load double, double* %133
%135 = tail call double @llvm.fmuladd.f64(double %132, double %134, double %129)
%136 = add nuw nsw i64 %128, 1
%137 = add i64 %130, 1
%138 = icmp eq i64 %137, %82
br i1 %138, label %139, label %127
139: ; preds = %122, %127, %1, %79
%140 = phi double [ 0.000000e+00, %79 ], [ 0.000000e+00, %1 ], [ %123, %122 ], [ %135, %127 ]
ret double %140
}