void matrix_vector(int n, double m[], double x[], double y[]) {
  int i, j;
  for (i = 0; i < n; i++) {
    y[i] = m[(n + 1) * i] * x[i];
    for (j = 0; j < i; j++)
      y[i] += m[i + n * j] * x[j];
    for (j = i + 1; j < n; j++)
      y[i] += m[n * i + j] * x[j];
  }
}


x86 assembly (clang, -O0):
<matrix_vector>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
movl   $0x0,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1229 <matrix_vector+0x129>
mov    -0x10(%rbp),%rax
mov    -0x4(%rbp),%ecx
add    $0x1,%ecx
imul   -0x24(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x24(%rbp),%rcx
mulsd  (%rax,%rcx,8),%xmm0
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
movl   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    11b6 <matrix_vector+0xb6>
mov    -0x10(%rbp),%rax
mov    -0x24(%rbp),%ecx
mov    -0x4(%rbp),%edx
imul   -0x28(%rbp),%edx
add    %edx,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    115d <matrix_vector+0x5d>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1216 <matrix_vector+0x116>
mov    -0x10(%rbp),%rax
mov    -0x4(%rbp),%ecx
imul   -0x24(%rbp),%ecx
add    -0x28(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    11bf <matrix_vector+0xbf>
jmp    121b <matrix_vector+0x11b>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    111a <matrix_vector+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<matrix_vector>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
test   %edi,%edi
jle    1234 <matrix_vector+0x134>
mov    %edi,%r10d
add    $0x1,%edi
mov    %r10,%r8
shl    $0x4,%r8
lea    0x8(,%r10,8),%rax
mov    %rax,-0x8(%rsp)
xor    %r12d,%r12d
mov    %r10,%r11
mov    %rdx,%r15
mov    %rsi,%r13
mov    %rsi,%r14
jmp    115a <matrix_vector+0x5a>
nopl   (%rax)
add    $0x8,%r14
add    -0x8(%rsp),%r13
add    $0x8,%r15
add    $0xffffffffffffffff,%r11
cmp    %r10,%r12
je     1234 <matrix_vector+0x134>
mov    %r12,%rax
mov    %r12,%rbx
imul   %rdi,%rbx
movsd  (%rsi,%rbx,8),%xmm0
mulsd  (%rdx,%r12,8),%xmm0
movsd  %xmm0,(%rcx,%r12,8)
test   %r12,%r12
je     11f9 <matrix_vector+0xf9>
cmp    $0x1,%rax
jne    1190 <matrix_vector+0x90>
xor    %r9d,%r9d
jmp    11d7 <matrix_vector+0xd7>
nopl   0x0(%rax)
mov    %rax,%r12
and    $0xfffffffffffffffe,%r12
mov    %r14,%rbp
xor    %r9d,%r9d
nopl   (%rax)
movsd  0x0(%rbp),%xmm1
mulsd  (%rdx,%r9,8),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%rcx,%rax,8)
movsd  0x0(%rbp,%r10,8),%xmm0
mulsd  0x8(%rdx,%r9,8),%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rcx,%rax,8)
add    $0x2,%r9
add    %r8,%rbp
cmp    %r9,%r12
jne    11a0 <matrix_vector+0xa0>
test   $0x1,%al
je     11f9 <matrix_vector+0xf9>
mov    %r9,%rbx
imul   %r10,%rbx
add    %rax,%rbx
movsd  (%rsi,%rbx,8),%xmm1
mulsd  (%rdx,%r9,8),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rcx,%rax,8)
lea    0x1(%rax),%r12
cmp    %r10,%r12
jae    1140 <matrix_vector+0x40>
mov    $0x1,%ebx
nopl   0x0(%rax,%rax,1)
movsd  0x0(%r13,%rbx,8),%xmm1
mulsd  (%r15,%rbx,8),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rcx,%rax,8)
add    $0x1,%rbx
cmp    %rbx,%r11
jne    1210 <matrix_vector+0x110>
jmp    1140 <matrix_vector+0x40>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @matrix_vector(i32 %0, double* %1, double* %2, double* %3) {
%5 = alloca i32
%6 = alloca double*
%7 = alloca double*
%8 = alloca double*
%9 = alloca i32
%10 = alloca i32
store i32 %0, i32* %5
store double* %1, double** %6
store double* %2, double** %7
store double* %3, double** %8
store i32 0, i32* %9
br label %11
11: ; preds = %94, %4
%12 = load i32, i32* %9
%13 = load i32, i32* %5
%14 = icmp slt i32 %12, %13
br i1 %14, label %15, label %97
15: ; preds = %11
%16 = load double*, double** %6
%17 = load i32, i32* %5
%18 = add nsw i32 %17, 1
%19 = load i32, i32* %9
%20 = mul nsw i32 %18, %19
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds double, double* %16, i64 %21
%23 = load double, double* %22
%24 = load double*, double** %7
%25 = load i32, i32* %9
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds double, double* %24, i64 %26
%28 = load double, double* %27
%29 = fmul double %23, %28
%30 = load double*, double** %8
%31 = load i32, i32* %9
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds double, double* %30, i64 %32
store double %29, double* %33
store i32 0, i32* %10
br label %34
34: ; preds = %59, %15
%35 = load i32, i32* %10
%36 = load i32, i32* %9
%37 = icmp slt i32 %35, %36
br i1 %37, label %38, label %62
38: ; preds = %34
%39 = load double*, double** %6
%40 = load i32, i32* %9
%41 = load i32, i32* %5
%42 = load i32, i32* %10
%43 = mul nsw i32 %41, %42
%44 = add nsw i32 %40, %43
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds double, double* %39, i64 %45
%47 = load double, double* %46
%48 = load double*, double** %7
%49 = load i32, i32* %10
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds double, double* %48, i64 %50
%52 = load double, double* %51
%53 = load double*, double** %8
%54 = load i32, i32* %9
%55 = sext i32 %54 to i64
%56 = getelementptr inbounds double, double* %53, i64 %55
%57 = load double, double* %56
%58 = call double @llvm.fmuladd.f64(double %47, double %52, double %57)
store double %58, double* %56
br label %59
59: ; preds = %38
%60 = load i32, i32* %10
%61 = add nsw i32 %60, 1
store i32 %61, i32* %10
br label %34
62: ; preds = %34
%63 = load i32, i32* %9
%64 = add nsw i32 %63, 1
store i32 %64, i32* %10
br label %65
65: ; preds = %90, %62
%66 = load i32, i32* %10
%67 = load i32, i32* %5
%68 = icmp slt i32 %66, %67
br i1 %68, label %69, label %93
69: ; preds = %65
%70 = load double*, double** %6
%71 = load i32, i32* %5
%72 = load i32, i32* %9
%73 = mul nsw i32 %71, %72
%74 = load i32, i32* %10
%75 = add nsw i32 %73, %74
%76 = sext i32 %75 to i64
%77 = getelementptr inbounds double, double* %70, i64 %76
%78 = load double, double* %77
%79 = load double*, double** %7
%80 = load i32, i32* %10
%81 = sext i32 %80 to i64
%82 = getelementptr inbounds double, double* %79, i64 %81
%83 = load double, double* %82
%84 = load double*, double** %8
%85 = load i32, i32* %9
%86 = sext i32 %85 to i64
%87 = getelementptr inbounds double, double* %84, i64 %86
%88 = load double, double* %87
%89 = call double @llvm.fmuladd.f64(double %78, double %83, double %88)
store double %89, double* %87
br label %90
90: ; preds = %69
%91 = load i32, i32* %10
%92 = add nsw i32 %91, 1
store i32 %92, i32* %10
br label %65
93: ; preds = %65
br label %94
94: ; preds = %93
%95 = load i32, i32* %9
%96 = add nsw i32 %95, 1
store i32 %96, i32* %9
br label %11
97: ; preds = %11
ret void
}

LLVM IR (-O2):
define void @matrix_vector(i32 %0, double* nocapture %1, double* nocapture %2, double* nocapture %3) {
%5 = icmp sgt i32 %0, 0
br i1 %5, label %6, label %82
6: ; preds = %4
%7 = add nuw nsw i32 %0, 1
%8 = zext i32 %0 to i64
%9 = zext i32 %7 to i64
%10 = zext i32 %0 to i64
br label %14
11: ; preds = %71, %65
%12 = add nuw nsw i64 %16, 1
%13 = icmp eq i64 %67, %10
br i1 %13, label %82, label %14
14: ; preds = %6, %11
%15 = phi i64 [ 0, %6 ], [ %67, %11 ]
%16 = phi i64 [ 1, %6 ], [ %12, %11 ]
%17 = mul nsw i64 %15, %9
%18 = getelementptr inbounds double, double* %1, i64 %17
%19 = load double, double* %18
%20 = getelementptr inbounds double, double* %2, i64 %15
%21 = load double, double* %20
%22 = fmul double %19, %21
%23 = getelementptr inbounds double, double* %3, i64 %15
store double %22, double* %23
%24 = icmp eq i64 %15, 0
br i1 %24, label %65, label %25
25: ; preds = %14
%26 = and i64 %15, 1
%27 = icmp eq i64 %15, 1
br i1 %27, label %52, label %28
28: ; preds = %25
%29 = and i64 %15, 9223372036854775806
br label %30
30: ; preds = %30, %28
%31 = phi double [ %22, %28 ], [ %48, %30 ]
%32 = phi i64 [ 0, %28 ], [ %49, %30 ]
%33 = phi i64 [ 0, %28 ], [ %50, %30 ]
%34 = mul nsw i64 %32, %8
%35 = add nuw nsw i64 %34, %15
%36 = getelementptr inbounds double, double* %1, i64 %35
%37 = load double, double* %36
%38 = getelementptr inbounds double, double* %2, i64 %32
%39 = load double, double* %38
%40 = tail call double @llvm.fmuladd.f64(double %37, double %39, double %31)
store double %40, double* %23
%41 = or i64 %32, 1
%42 = mul nsw i64 %41, %8
%43 = add nuw nsw i64 %42, %15
%44 = getelementptr inbounds double, double* %1, i64 %43
%45 = load double, double* %44
%46 = getelementptr inbounds double, double* %2, i64 %41
%47 = load double, double* %46
%48 = tail call double @llvm.fmuladd.f64(double %45, double %47, double %40)
store double %48, double* %23
%49 = add nuw nsw i64 %32, 2
%50 = add i64 %33, 2
%51 = icmp eq i64 %50, %29
br i1 %51, label %52, label %30
52: ; preds = %30, %25
%53 = phi double [ undef, %25 ], [ %48, %30 ]
%54 = phi double [ %22, %25 ], [ %48, %30 ]
%55 = phi i64 [ 0, %25 ], [ %49, %30 ]
%56 = icmp eq i64 %26, 0
br i1 %56, label %65, label %57
57: ; preds = %52
%58 = mul nsw i64 %55, %8
%59 = add nuw nsw i64 %58, %15
%60 = getelementptr inbounds double, double* %1, i64 %59
%61 = load double, double* %60
%62 = getelementptr inbounds double, double* %2, i64 %55
%63 = load double, double* %62
%64 = tail call double @llvm.fmuladd.f64(double %61, double %63, double %54)
store double %64, double* %23
br label %65
65: ; preds = %57, %52, %14
%66 = phi double [ %22, %14 ], [ %53, %52 ], [ %64, %57 ]
%67 = add nuw nsw i64 %15, 1
%68 = icmp ult i64 %67, %8
br i1 %68, label %69, label %11
69: ; preds = %65
%70 = mul nsw i64 %15, %8
br label %71
71: ; preds = %69, %71
%72 = phi double [ %66, %69 ], [ %79, %71 ]
%73 = phi i64 [ %16, %69 ], [ %80, %71 ]
%74 = add nuw nsw i64 %73, %70
%75 = getelementptr inbounds double, double* %1, i64 %74
%76 = load double, double* %75
%77 = getelementptr inbounds double, double* %2, i64 %73
%78 = load double, double* %77
%79 = tail call double @llvm.fmuladd.f64(double %76, double %78, double %72)
store double %79, double* %23
%80 = add nuw nsw i64 %73, 1
%81 = icmp eq i64 %80, %10
br i1 %81, label %11, label %71
82: ; preds = %11, %4
ret void
}