void kernel_dgemv_n_4_vs_lib4(int km, int kmax, double *A, double *x, double *y,
                              double *z, int alg) {
  if (kmax <= 0)
    return;
  __builtin_prefetch(A);
  __builtin_prefetch(A + 8);
  const int lda = 4;
  int k;
  double x_0, x_1, x_2, x_3, y_0 = 0, y_1 = 0, y_2 = 0, y_3 = 0;
  k = 0;
  for (; k < kmax - 3; k += 4) {
    __builtin_prefetch(A + 4 * lda);
    __builtin_prefetch(A + 4 * lda + 8);
    x_0 = x[0];
    x_1 = x[1];
    x_2 = x[2];
    x_3 = x[3];
    y_0 += A[0 + lda * 0] * x_0;
    y_1 += A[1 + lda * 0] * x_0;
    y_2 += A[2 + lda * 0] * x_0;
    y_3 += A[3 + lda * 0] * x_0;
    y_0 += A[0 + lda * 1] * x_1;
    y_1 += A[1 + lda * 1] * x_1;
    y_2 += A[2 + lda * 1] * x_1;
    y_3 += A[3 + lda * 1] * x_1;
    y_0 += A[0 + lda * 2] * x_2;
    y_1 += A[1 + lda * 2] * x_2;
    y_2 += A[2 + lda * 2] * x_2;
    y_3 += A[3 + lda * 2] * x_2;
    y_0 += A[0 + lda * 3] * x_3;
    y_1 += A[1 + lda * 3] * x_3;
    y_2 += A[2 + lda * 3] * x_3;
    y_3 += A[3 + lda * 3] * x_3;
    A += 4 * lda;
    x += 4;
  }
  for (; k < kmax; k++) {
    x_0 = x[0];
    y_0 += A[0 + lda * 0] * x_0;
    y_1 += A[1 + lda * 0] * x_0;
    y_2 += A[2 + lda * 0] * x_0;
    y_3 += A[3 + lda * 0] * x_0;
    A += 1 * lda;
    x += 1;
  }
  if (alg == 0) {
    goto store;
  } else if (alg == 1) {
    y_0 += y[0];
    y_1 += y[1];
    y_2 += y[2];
    y_3 += y[3];
    goto store;
  } else {
    y_0 = y[0] - y_0;
    y_1 = y[1] - y_1;
    y_2 = y[2] - y_2;
    y_3 = y[3] - y_3;
    goto store;
  }
store:
  if (km >= 4) {
    z[0] = y_0;
    z[1] = y_1;
    z[2] = y_2;
    z[3] = y_3;
  } else {
    z[0] = y_0;
    if (km >= 2) {
      z[1] = y_1;
      if (km > 2) {
        z[2] = y_2;
      }
    }
  }
}


x86 assembly (clang, -O0):
<kernel_dgemv_n_4_vs_lib4>:
push   %rbp
mov    %rsp,%rbp
mov    0x10(%rbp),%eax
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %rdx,-0x10(%rbp)
mov    %rcx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
cmpl   $0x0,-0x8(%rbp)
jg     112c <kernel_dgemv_n_4_vs_lib4+0x2c>
jmp    15fd <kernel_dgemv_n_4_vs_lib4+0x4fd>
mov    -0x10(%rbp),%rax
prefetcht0 (%rax)
mov    -0x10(%rbp),%rax
add    $0x40,%rax
prefetcht0 (%rax)
movl   $0x4,-0x2c(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x58(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x60(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x68(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x70(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
mov    -0x8(%rbp),%ecx
sub    $0x3,%ecx
cmp    %ecx,%eax
jge    13f9 <kernel_dgemv_n_4_vs_lib4+0x2f9>
mov    -0x10(%rbp),%rax
add    $0x80,%rax
prefetcht0 (%rax)
mov    -0x10(%rbp),%rax
add    $0x80,%rax
add    $0x40,%rax
prefetcht0 (%rax)
mov    -0x18(%rbp),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x18(%rbp),%rax
movsd  0x8(%rax),%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x18(%rbp),%rax
movsd  0x10(%rax),%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x18(%rbp),%rax
movsd  0x18(%rax),%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x58(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x60(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x68(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x18(%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x70(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x20(%rax),%xmm0
movsd  -0x40(%rbp),%xmm2
movsd  -0x58(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x28(%rax),%xmm0
movsd  -0x40(%rbp),%xmm2
movsd  -0x60(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x30(%rax),%xmm0
movsd  -0x40(%rbp),%xmm2
movsd  -0x68(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x38(%rax),%xmm0
movsd  -0x40(%rbp),%xmm2
movsd  -0x70(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x40(%rax),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x58(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x48(%rax),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x60(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x50(%rax),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x68(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x58(%rax),%xmm0
movsd  -0x48(%rbp),%xmm2
movsd  -0x70(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x60(%rax),%xmm0
movsd  -0x50(%rbp),%xmm2
movsd  -0x58(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x68(%rax),%xmm0
movsd  -0x50(%rbp),%xmm2
movsd  -0x60(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x70(%rax),%xmm0
movsd  -0x50(%rbp),%xmm2
movsd  -0x68(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x78(%rax),%xmm0
movsd  -0x50(%rbp),%xmm2
movsd  -0x70(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x10(%rbp),%rax
add    $0x80,%rax
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rax
add    $0x20,%rax
mov    %rax,-0x18(%rbp)
mov    -0x30(%rbp),%eax
add    $0x4,%eax
mov    %eax,-0x30(%rbp)
jmp    116c <kernel_dgemv_n_4_vs_lib4+0x6c>
jmp    13fe <kernel_dgemv_n_4_vs_lib4+0x2fe>
mov    -0x30(%rbp),%eax
cmp    -0x8(%rbp),%eax
jge    14bc <kernel_dgemv_n_4_vs_lib4+0x3bc>
mov    -0x18(%rbp),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x58(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x60(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x68(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x18(%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
movsd  -0x70(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x10(%rbp),%rax
add    $0x20,%rax
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rax
add    $0x8,%rax
mov    %rax,-0x18(%rbp)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    13fe <kernel_dgemv_n_4_vs_lib4+0x2fe>
cmpl   $0x0,0x10(%rbp)
jne    14cb <kernel_dgemv_n_4_vs_lib4+0x3cb>
jmp    1570 <kernel_dgemv_n_4_vs_lib4+0x470>
cmpl   $0x1,0x10(%rbp)
jne    1525 <kernel_dgemv_n_4_vs_lib4+0x425>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
addsd  -0x58(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x20(%rbp),%rax
movsd  0x8(%rax),%xmm0
addsd  -0x60(%rbp),%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x20(%rbp),%rax
movsd  0x10(%rax),%xmm0
addsd  -0x68(%rbp),%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x20(%rbp),%rax
movsd  0x18(%rax),%xmm0
addsd  -0x70(%rbp),%xmm0
movsd  %xmm0,-0x70(%rbp)
jmp    1570 <kernel_dgemv_n_4_vs_lib4+0x470>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
subsd  -0x58(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x20(%rbp),%rax
movsd  0x8(%rax),%xmm0
subsd  -0x60(%rbp),%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x20(%rbp),%rax
movsd  0x10(%rax),%xmm0
subsd  -0x68(%rbp),%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x20(%rbp),%rax
movsd  0x18(%rax),%xmm0
subsd  -0x70(%rbp),%xmm0
movsd  %xmm0,-0x70(%rbp)
cmpl   $0x4,-0x4(%rbp)
jl     15b6 <kernel_dgemv_n_4_vs_lib4+0x4b6>
movsd  -0x58(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x60(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x8(%rax)
movsd  -0x68(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x10(%rax)
movsd  -0x70(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x18(%rax)
jmp    15fd <kernel_dgemv_n_4_vs_lib4+0x4fd>
movsd  -0x58(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,(%rax)
cmpl   $0x2,-0x4(%rbp)
jl     15f8 <kernel_dgemv_n_4_vs_lib4+0x4f8>
movsd  -0x60(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x8(%rax)
cmpl   $0x2,-0x4(%rbp)
jle    15f3 <kernel_dgemv_n_4_vs_lib4+0x4f3>
movsd  -0x68(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x10(%rax)
jmp    15f8 <kernel_dgemv_n_4_vs_lib4+0x4f8>
jmp    15fd <kernel_dgemv_n_4_vs_lib4+0x4fd>
pop    %rbp
ret

x86 assembly (clang, -O2):
<kernel_dgemv_n_4_vs_lib4>:
test   %esi,%esi
jle    1305 <kernel_dgemv_n_4_vs_lib4+0x205>
prefetcht0 (%rdx)
prefetcht0 0x40(%rdx)
cmp    $0x4,%esi
jb     120a <kernel_dgemv_n_4_vs_lib4+0x10a>
lea    -0x3(%rsi),%r10d
xorpd  %xmm4,%xmm4
xor    %eax,%eax
xorpd  %xmm5,%xmm5
cs nopw 0x0(%rax,%rax,1)
prefetcht0 0x80(%rdx)
prefetcht0 0xc0(%rdx)
movupd 0x8(%rdx),%xmm0
movsd  (%rcx),%xmm1
movsd  0x8(%rcx),%xmm3
unpcklpd %xmm1,%xmm1
mulpd  %xmm1,%xmm0
movsd  (%rdx),%xmm2
movhpd 0x18(%rdx),%xmm2
addpd  %xmm4,%xmm0
mulpd  %xmm1,%xmm2
addpd  %xmm5,%xmm2
movupd 0x28(%rdx),%xmm4
unpcklpd %xmm3,%xmm3
mulpd  %xmm3,%xmm4
addpd  %xmm0,%xmm4
movsd  0x20(%rdx),%xmm5
movhpd 0x38(%rdx),%xmm5
mulpd  %xmm3,%xmm5
movupd 0x48(%rdx),%xmm3
movsd  0x40(%rdx),%xmm6
movhpd 0x58(%rdx),%xmm6
movupd 0x68(%rdx),%xmm0
movsd  0x60(%rdx),%xmm1
movhpd 0x78(%rdx),%xmm1
lea    0x80(%rdx),%rdx
addpd  %xmm2,%xmm5
movsd  0x10(%rcx),%xmm2
unpcklpd %xmm2,%xmm2
mulpd  %xmm2,%xmm3
addpd  %xmm4,%xmm3
movsd  0x18(%rcx),%xmm7
mulpd  %xmm2,%xmm6
addpd  %xmm5,%xmm6
unpcklpd %xmm7,%xmm7
mulpd  %xmm7,%xmm0
movapd %xmm0,%xmm4
addpd  %xmm3,%xmm4
mulpd  %xmm7,%xmm1
movapd %xmm1,%xmm5
addpd  %xmm6,%xmm5
add    $0x20,%rcx
add    $0x4,%eax
cmp    %r10d,%eax
jl     1130 <kernel_dgemv_n_4_vs_lib4+0x30>
addpd  %xmm6,%xmm1
addpd  %xmm3,%xmm0
mov    %esi,%eax
and    $0xfffffffc,%eax
jmp    1214 <kernel_dgemv_n_4_vs_lib4+0x114>
xorpd  %xmm0,%xmm0
xor    %eax,%eax
xorpd  %xmm1,%xmm1
mov    0x8(%rsp),%r10d
cmp    %esi,%eax
jge    1283 <kernel_dgemv_n_4_vs_lib4+0x183>
sub    %eax,%esi
xor    %eax,%eax
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movapd %xmm1,%xmm3
movapd %xmm0,%xmm2
movupd 0x8(%rdx),%xmm4
movsd  (%rcx,%rax,8),%xmm1
unpcklpd %xmm1,%xmm1
mulpd  %xmm1,%xmm4
movapd %xmm4,%xmm0
addpd  %xmm2,%xmm0
movsd  (%rdx),%xmm5
movhpd 0x18(%rdx),%xmm5
mulpd  %xmm1,%xmm5
movapd %xmm5,%xmm1
addpd  %xmm3,%xmm1
add    $0x1,%rax
add    $0x20,%rdx
cmp    %eax,%esi
jne    1230 <kernel_dgemv_n_4_vs_lib4+0x130>
addpd  %xmm3,%xmm5
addpd  %xmm2,%xmm4
movapd %xmm4,%xmm0
movapd %xmm5,%xmm1
test   %r10d,%r10d
je     12ca <kernel_dgemv_n_4_vs_lib4+0x1ca>
cmp    $0x1,%r10d
jne    12a9 <kernel_dgemv_n_4_vs_lib4+0x1a9>
movupd 0x8(%r8),%xmm2
addpd  %xmm2,%xmm0
movsd  (%r8),%xmm2
movhpd 0x18(%r8),%xmm2
addpd  %xmm2,%xmm1
jmp    12ca <kernel_dgemv_n_4_vs_lib4+0x1ca>
movupd 0x8(%r8),%xmm2
subpd  %xmm0,%xmm2
movsd  (%r8),%xmm3
movhpd 0x18(%r8),%xmm3
subpd  %xmm1,%xmm3
movapd %xmm2,%xmm0
movapd %xmm3,%xmm1
movlpd %xmm1,(%r9)
cmp    $0x4,%edi
jl     12e5 <kernel_dgemv_n_4_vs_lib4+0x1e5>
movupd %xmm0,0x8(%r9)
unpckhpd %xmm1,%xmm1
mov    $0x3,%eax
jmp    12ff <kernel_dgemv_n_4_vs_lib4+0x1ff>
cmp    $0x2,%edi
jl     1305 <kernel_dgemv_n_4_vs_lib4+0x205>
movlpd %xmm0,0x8(%r9)
je     1305 <kernel_dgemv_n_4_vs_lib4+0x205>
unpckhpd %xmm0,%xmm0
mov    $0x2,%eax
movapd %xmm0,%xmm1
movsd  %xmm1,(%r9,%rax,8)
ret

LLVM IR (-O0):
define void @kernel_dgemv_n_4_vs_lib4(i32 %0, i32 %1, double* %2, double* %3, double* %4, double* %5, i32 %6) {
%8 = alloca i32
%9 = alloca i32
%10 = alloca double*
%11 = alloca double*
%12 = alloca double*
%13 = alloca double*
%14 = alloca i32
%15 = alloca i32
%16 = alloca i32
%17 = alloca double
%18 = alloca double
%19 = alloca double
%20 = alloca double
%21 = alloca double
%22 = alloca double
%23 = alloca double
%24 = alloca double
store i32 %0, i32* %8
store i32 %1, i32* %9
store double* %2, double** %10
store double* %3, double** %11
store double* %4, double** %12
store double* %5, double** %13
store i32 %6, i32* %14
%25 = load i32, i32* %9
%26 = icmp sle i32 %25, 0
br i1 %26, label %27, label %28
27: ; preds = %7
br label %285
28: ; preds = %7
%29 = load double*, double** %10
%30 = bitcast double* %29 to i8*
%31 = load double*, double** %10
%32 = getelementptr inbounds double, double* %31, i64 8
%33 = bitcast double* %32 to i8*
store i32 4, i32* %15
store double 0.000000e+00, double* %21
store double 0.000000e+00, double* %22
store double 0.000000e+00, double* %23
store double 0.000000e+00, double* %24
store i32 0, i32* %16
br label %34
34: ; preds = %159, %28
%35 = load i32, i32* %16
%36 = load i32, i32* %9
%37 = sub nsw i32 %36, 3
%38 = icmp slt i32 %35, %37
br i1 %38, label %39, label %162
39: ; preds = %34
%40 = load double*, double** %10
%41 = getelementptr inbounds double, double* %40, i64 16
%42 = bitcast double* %41 to i8*
%43 = load double*, double** %10
%44 = getelementptr inbounds double, double* %43, i64 16
%45 = getelementptr inbounds double, double* %44, i64 8
%46 = bitcast double* %45 to i8*
%47 = load double*, double** %11
%48 = getelementptr inbounds double, double* %47, i64 0
%49 = load double, double* %48
store double %49, double* %17
%50 = load double*, double** %11
%51 = getelementptr inbounds double, double* %50, i64 1
%52 = load double, double* %51
store double %52, double* %18
%53 = load double*, double** %11
%54 = getelementptr inbounds double, double* %53, i64 2
%55 = load double, double* %54
store double %55, double* %19
%56 = load double*, double** %11
%57 = getelementptr inbounds double, double* %56, i64 3
%58 = load double, double* %57
store double %58, double* %20
%59 = load double*, double** %10
%60 = getelementptr inbounds double, double* %59, i64 0
%61 = load double, double* %60
%62 = load double, double* %17
%63 = load double, double* %21
%64 = call double @llvm.fmuladd.f64(double %61, double %62, double %63)
store double %64, double* %21
%65 = load double*, double** %10
%66 = getelementptr inbounds double, double* %65, i64 1
%67 = load double, double* %66
%68 = load double, double* %17
%69 = load double, double* %22
%70 = call double @llvm.fmuladd.f64(double %67, double %68, double %69)
store double %70, double* %22
%71 = load double*, double** %10
%72 = getelementptr inbounds double, double* %71, i64 2
%73 = load double, double* %72
%74 = load double, double* %17
%75 = load double, double* %23
%76 = call double @llvm.fmuladd.f64(double %73, double %74, double %75)
store double %76, double* %23
%77 = load double*, double** %10
%78 = getelementptr inbounds double, double* %77, i64 3
%79 = load double, double* %78
%80 = load double, double* %17
%81 = load double, double* %24
%82 = call double @llvm.fmuladd.f64(double %79, double %80, double %81)
store double %82, double* %24
%83 = load double*, double** %10
%84 = getelementptr inbounds double, double* %83, i64 4
%85 = load double, double* %84
%86 = load double, double* %18
%87 = load double, double* %21
%88 = call double @llvm.fmuladd.f64(double %85, double %86, double %87)
store double %88, double* %21
%89 = load double*, double** %10
%90 = getelementptr inbounds double, double* %89, i64 5
%91 = load double, double* %90
%92 = load double, double* %18
%93 = load double, double* %22
%94 = call double @llvm.fmuladd.f64(double %91, double %92, double %93)
store double %94, double* %22
%95 = load double*, double** %10
%96 = getelementptr inbounds double, double* %95, i64 6
%97 = load double, double* %96
%98 = load double, double* %18
%99 = load double, double* %23
%100 = call double @llvm.fmuladd.f64(double %97, double %98, double %99)
store double %100, double* %23
%101 = load double*, double** %10
%102 = getelementptr inbounds double, double* %101, i64 7
%103 = load double, double* %102
%104 = load double, double* %18
%105 = load double, double* %24
%106 = call double @llvm.fmuladd.f64(double %103, double %104, double %105)
store double %106, double* %24
%107 = load double*, double** %10
%108 = getelementptr inbounds double, double* %107, i64 8
%109 = load double, double* %108
%110 = load double, double* %19
%111 = load double, double* %21
%112 = call double @llvm.fmuladd.f64(double %109, double %110, double %111)
store double %112, double* %21
%113 = load double*, double** %10
%114 = getelementptr inbounds double, double* %113, i64 9
%115 = load double, double* %114
%116 = load double, double* %19
%117 = load double, double* %22
%118 = call double @llvm.fmuladd.f64(double %115, double %116, double %117)
store double %118, double* %22
%119 = load double*, double** %10
%120 = getelementptr inbounds double, double* %119, i64 10
%121 = load double, double* %120
%122 = load double, double* %19
%123 = load double, double* %23
%124 = call double @llvm.fmuladd.f64(double %121, double %122, double %123)
store double %124, double* %23
%125 = load double*, double** %10
%126 = getelementptr inbounds double, double* %125, i64 11
%127 = load double, double* %126
%128 = load double, double* %19
%129 = load double, double* %24
%130 = call double @llvm.fmuladd.f64(double %127, double %128, double %129)
store double %130, double* %24
%131 = load double*, double** %10
%132 = getelementptr inbounds double, double* %131, i64 12
%133 = load double, double* %132
%134 = load double, double* %20
%135 = load double, double* %21
%136 = call double @llvm.fmuladd.f64(double %133, double %134, double %135)
store double %136, double* %21
%137 = load double*, double** %10
%138 = getelementptr inbounds double, double* %137, i64 13
%139 = load double, double* %138
%140 = load double, double* %20
%141 = load double, double* %22
%142 = call double @llvm.fmuladd.f64(double %139, double %140, double %141)
store double %142, double* %22
%143 = load double*, double** %10
%144 = getelementptr inbounds double, double* %143, i64 14
%145 = load double, double* %144
%146 = load double, double* %20
%147 = load double, double* %23
%148 = call double @llvm.fmuladd.f64(double %145, double %146, double %147)
store double %148, double* %23
%149 = load double*, double** %10
%150 = getelementptr inbounds double, double* %149, i64 15
%151 = load double, double* %150
%152 = load double, double* %20
%153 = load double, double* %24
%154 = call double @llvm.fmuladd.f64(double %151, double %152, double %153)
store double %154, double* %24
%155 = load double*, double** %10
%156 = getelementptr inbounds double, double* %155, i64 16
store double* %156, double** %10
%157 = load double*, double** %11
%158 = getelementptr inbounds double, double* %157, i64 4
store double* %158, double** %11
br label %159
159: ; preds = %39
%160 = load i32, i32* %16
%161 = add nsw i32 %160, 4
store i32 %161, i32* %16
br label %34
162: ; preds = %34
br label %163
163: ; preds = %199, %162
%164 = load i32, i32* %16
%165 = load i32, i32* %9
%166 = icmp slt i32 %164, %165
br i1 %166, label %167, label %202
167: ; preds = %163
%168 = load double*, double** %11
%169 = getelementptr inbounds double, double* %168, i64 0
%170 = load double, double* %169
store double %170, double* %17
%171 = load double*, double** %10
%172 = getelementptr inbounds double, double* %171, i64 0
%173 = load double, double* %172
%174 = load double, double* %17
%175 = load double, double* %21
%176 = call double @llvm.fmuladd.f64(double %173, double %174, double %175)
store double %176, double* %21
%177 = load double*, double** %10
%178 = getelementptr inbounds double, double* %177, i64 1
%179 = load double, double* %178
%180 = load double, double* %17
%181 = load double, double* %22
%182 = call double @llvm.fmuladd.f64(double %179, double %180, double %181)
store double %182, double* %22
%183 = load double*, double** %10
%184 = getelementptr inbounds double, double* %183, i64 2
%185 = load double, double* %184
%186 = load double, double* %17
%187 = load double, double* %23
%188 = call double @llvm.fmuladd.f64(double %185, double %186, double %187)
store double %188, double* %23
%189 = load double*, double** %10
%190 = getelementptr inbounds double, double* %189, i64 3
%191 = load double, double* %190
%192 = load double, double* %17
%193 = load double, double* %24
%194 = call double @llvm.fmuladd.f64(double %191, double %192, double %193)
store double %194, double* %24
%195 = load double*, double** %10
%196 = getelementptr inbounds double, double* %195, i64 4
store double* %196, double** %10
%197 = load double*, double** %11
%198 = getelementptr inbounds double, double* %197, i64 1
store double* %198, double** %11
br label %199
199: ; preds = %167
%200 = load i32, i32* %16
%201 = add nsw i32 %200, 1
store i32 %201, i32* %16
br label %163
202: ; preds = %163
%203 = load i32, i32* %14
%204 = icmp eq i32 %203, 0
br i1 %204, label %205, label %206
205: ; preds = %202
br label %251
206: ; preds = %202
%207 = load i32, i32* %14
%208 = icmp eq i32 %207, 1
br i1 %208, label %209, label %230
209: ; preds = %206
%210 = load double*, double** %12
%211 = getelementptr inbounds double, double* %210, i64 0
%212 = load double, double* %211
%213 = load double, double* %21
%214 = fadd double %213, %212
store double %214, double* %21
%215 = load double*, double** %12
%216 = getelementptr inbounds double, double* %215, i64 1
%217 = load double, double* %216
%218 = load double, double* %22
%219 = fadd double %218, %217
store double %219, double* %22
%220 = load double*, double** %12
%221 = getelementptr inbounds double, double* %220, i64 2
%222 = load double, double* %221
%223 = load double, double* %23
%224 = fadd double %223, %222
store double %224, double* %23
%225 = load double*, double** %12
%226 = getelementptr inbounds double, double* %225, i64 3
%227 = load double, double* %226
%228 = load double, double* %24
%229 = fadd double %228, %227
store double %229, double* %24
br label %251
230: ; preds = %206
%231 = load double*, double** %12
%232 = getelementptr inbounds double, double* %231, i64 0
%233 = load double, double* %232
%234 = load double, double* %21
%235 = fsub double %233, %234
store double %235, double* %21
%236 = load double*, double** %12
%237 = getelementptr inbounds double, double* %236, i64 1
%238 = load double, double* %237
%239 = load double, double* %22
%240 = fsub double %238, %239
store double %240, double* %22
%241 = load double*, double** %12
%242 = getelementptr inbounds double, double* %241, i64 2
%243 = load double, double* %242
%244 = load double, double* %23
%245 = fsub double %243, %244
store double %245, double* %23
%246 = load double*, double** %12
%247 = getelementptr inbounds double, double* %246, i64 3
%248 = load double, double* %247
%249 = load double, double* %24
%250 = fsub double %248, %249
store double %250, double* %24
br label %251
251: ; preds = %230, %209, %205
%252 = load i32, i32* %8
%253 = icmp sge i32 %252, 4
br i1 %253, label %254, label %267
254: ; preds = %251
%255 = load double, double* %21
%256 = load double*, double** %13
%257 = getelementptr inbounds double, double* %256, i64 0
store double %255, double* %257
%258 = load double, double* %22
%259 = load double*, double** %13
%260 = getelementptr inbounds double, double* %259, i64 1
store double %258, double* %260
%261 = load double, double* %23
%262 = load double*, double** %13
%263 = getelementptr inbounds double, double* %262, i64 2
store double %261, double* %263
%264 = load double, double* %24
%265 = load double*, double** %13
%266 = getelementptr inbounds double, double* %265, i64 3
store double %264, double* %266
br label %285
267: ; preds = %251
%268 = load double, double* %21
%269 = load double*, double** %13
%270 = getelementptr inbounds double, double* %269, i64 0
store double %268, double* %270
%271 = load i32, i32* %8
%272 = icmp sge i32 %271, 2
br i1 %272, label %273, label %284
273: ; preds = %267
%274 = load double, double* %22
%275 = load double*, double** %13
%276 = getelementptr inbounds double, double* %275, i64 1
store double %274, double* %276
%277 = load i32, i32* %8
%278 = icmp sgt i32 %277, 2
br i1 %278, label %279, label %283
279: ; preds = %273
%280 = load double, double* %23
%281 = load double*, double** %13
%282 = getelementptr inbounds double, double* %281, i64 2
store double %280, double* %282
br label %283
283: ; preds = %279, %273
br label %284
284: ; preds = %283, %267
br label %285
285: ; preds = %27, %284, %254
ret void
}

LLVM IR (-O2):
define void @kernel_dgemv_n_4_vs_lib4(i32 %0, i32 %1, double* nocapture %2, double* nocapture %3, double* nocapture %4, double* nocapture writeonly %5, i32 %6) {
%8 = icmp slt i32 %1, 1
br i1 %8, label %174, label %9
9: ; preds = %7
%10 = bitcast double* %2 to i8*
tail call void @llvm.prefetch.p0i8(i8* %10, i32 0, i32 3, i32 1)
%11 = getelementptr inbounds double, double* %2, i64 8
%12 = bitcast double* %11 to i8*
tail call void @llvm.prefetch.p0i8(i8* %12, i32 0, i32 3, i32 1)
%13 = add nsw i32 %1, -3
%14 = icmp ugt i32 %1, 3
br i1 %14, label %32, label %25
15: ; preds = %32
%16 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %59, <2 x double> %54, <2 x double> %37)
%17 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %72, <2 x double> %67, <2 x double> %16)
%18 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %85, <2 x double> %80, <2 x double> %17)
%19 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %98, <2 x double> %93, <2 x double> %18)
%20 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %52, <2 x double> %54, <2 x double> %36)
%21 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %65, <2 x double> %67, <2 x double> %20)
%22 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %78, <2 x double> %80, <2 x double> %21)
%23 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %91, <2 x double> %93, <2 x double> %22)
%24 = and i32 %1, -4
br label %25
25: ; preds = %15, %9
%26 = phi i32 [ 0, %9 ], [ %24, %15 ]
%27 = phi double* [ %3, %9 ], [ %100, %15 ]
%28 = phi double* [ %2, %9 ], [ %38, %15 ]
%29 = phi <2 x double> [ zeroinitializer, %9 ], [ %23, %15 ]
%30 = phi <2 x double> [ zeroinitializer, %9 ], [ %19, %15 ]
%31 = icmp slt i32 %26, %1
br i1 %31, label %103, label %129
32: ; preds = %9, %32
%33 = phi double* [ %38, %32 ], [ %2, %9 ]
%34 = phi double* [ %100, %32 ], [ %3, %9 ]
%35 = phi i32 [ %101, %32 ], [ 0, %9 ]
%36 = phi <2 x double> [ %94, %32 ], [ zeroinitializer, %9 ]
%37 = phi <2 x double> [ %99, %32 ], [ zeroinitializer, %9 ]
%38 = getelementptr inbounds double, double* %33, i64 16
%39 = bitcast double* %38 to i8*
tail call void @llvm.prefetch.p0i8(i8* %39, i32 0, i32 3, i32 1)
%40 = getelementptr inbounds double, double* %33, i64 24
%41 = bitcast double* %40 to i8*
tail call void @llvm.prefetch.p0i8(i8* %41, i32 0, i32 3, i32 1)
%42 = load double, double* %34
%43 = getelementptr inbounds double, double* %34, i64 1
%44 = load double, double* %43
%45 = getelementptr inbounds double, double* %34, i64 2
%46 = load double, double* %45
%47 = getelementptr inbounds double, double* %34, i64 3
%48 = load double, double* %47
%49 = load double, double* %33
%50 = getelementptr inbounds double, double* %33, i64 1
%51 = bitcast double* %50 to <2 x double>*
%52 = load <2 x double>, <2 x double>* %51
%53 = insertelement <2 x double> poison, double %42, i64 0
%54 = shufflevector <2 x double> %53, <2 x double> poison, <2 x i32> zeroinitializer
%55 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %52, <2 x double> %54, <2 x double> %36)
%56 = getelementptr inbounds double, double* %33, i64 3
%57 = load double, double* %56
%58 = insertelement <2 x double> poison, double %49, i64 0
%59 = insertelement <2 x double> %58, double %57, i64 1
%60 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %59, <2 x double> %54, <2 x double> %37)
%61 = getelementptr inbounds double, double* %33, i64 4
%62 = load double, double* %61
%63 = getelementptr inbounds double, double* %33, i64 5
%64 = bitcast double* %63 to <2 x double>*
%65 = load <2 x double>, <2 x double>* %64
%66 = insertelement <2 x double> poison, double %44, i64 0
%67 = shufflevector <2 x double> %66, <2 x double> poison, <2 x i32> zeroinitializer
%68 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %65, <2 x double> %67, <2 x double> %55)
%69 = getelementptr inbounds double, double* %33, i64 7
%70 = load double, double* %69
%71 = insertelement <2 x double> poison, double %62, i64 0
%72 = insertelement <2 x double> %71, double %70, i64 1
%73 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %72, <2 x double> %67, <2 x double> %60)
%74 = getelementptr inbounds double, double* %33, i64 8
%75 = load double, double* %74
%76 = getelementptr inbounds double, double* %33, i64 9
%77 = bitcast double* %76 to <2 x double>*
%78 = load <2 x double>, <2 x double>* %77
%79 = insertelement <2 x double> poison, double %46, i64 0
%80 = shufflevector <2 x double> %79, <2 x double> poison, <2 x i32> zeroinitializer
%81 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %78, <2 x double> %80, <2 x double> %68)
%82 = getelementptr inbounds double, double* %33, i64 11
%83 = load double, double* %82
%84 = insertelement <2 x double> poison, double %75, i64 0
%85 = insertelement <2 x double> %84, double %83, i64 1
%86 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %85, <2 x double> %80, <2 x double> %73)
%87 = getelementptr inbounds double, double* %33, i64 12
%88 = load double, double* %87
%89 = getelementptr inbounds double, double* %33, i64 13
%90 = bitcast double* %89 to <2 x double>*
%91 = load <2 x double>, <2 x double>* %90
%92 = insertelement <2 x double> poison, double %48, i64 0
%93 = shufflevector <2 x double> %92, <2 x double> poison, <2 x i32> zeroinitializer
%94 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %91, <2 x double> %93, <2 x double> %81)
%95 = getelementptr inbounds double, double* %33, i64 15
%96 = load double, double* %95
%97 = insertelement <2 x double> poison, double %88, i64 0
%98 = insertelement <2 x double> %97, double %96, i64 1
%99 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %98, <2 x double> %93, <2 x double> %86)
%100 = getelementptr inbounds double, double* %34, i64 4
%101 = add nuw nsw i32 %35, 4
%102 = icmp slt i32 %101, %13
br i1 %102, label %32, label %15
103: ; preds = %25, %103
%104 = phi double* [ %122, %103 ], [ %28, %25 ]
%105 = phi double* [ %123, %103 ], [ %27, %25 ]
%106 = phi i32 [ %124, %103 ], [ %26, %25 ]
%107 = phi <2 x double> [ %116, %103 ], [ %29, %25 ]
%108 = phi <2 x double> [ %121, %103 ], [ %30, %25 ]
%109 = load double, double* %105
%110 = load double, double* %104
%111 = getelementptr inbounds double, double* %104, i64 1
%112 = bitcast double* %111 to <2 x double>*
%113 = load <2 x double>, <2 x double>* %112
%114 = insertelement <2 x double> poison, double %109, i64 0
%115 = shufflevector <2 x double> %114, <2 x double> poison, <2 x i32> zeroinitializer
%116 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %113, <2 x double> %115, <2 x double> %107)
%117 = getelementptr inbounds double, double* %104, i64 3
%118 = load double, double* %117
%119 = insertelement <2 x double> poison, double %110, i64 0
%120 = insertelement <2 x double> %119, double %118, i64 1
%121 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %120, <2 x double> %115, <2 x double> %108)
%122 = getelementptr inbounds double, double* %104, i64 4
%123 = getelementptr inbounds double, double* %105, i64 1
%124 = add nuw nsw i32 %106, 1
%125 = icmp eq i32 %124, %1
br i1 %125, label %126, label %103
126: ; preds = %103
%127 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %120, <2 x double> %115, <2 x double> %108)
%128 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %113, <2 x double> %115, <2 x double> %107)
br label %129
129: ; preds = %126, %25
%130 = phi <2 x double> [ %29, %25 ], [ %128, %126 ]
%131 = phi <2 x double> [ %30, %25 ], [ %127, %126 ]
switch i32 %6, label %143 [
i32 0, label %154
i32 1, label %132
]
132: ; preds = %129
%133 = load double, double* %4
%134 = getelementptr inbounds double, double* %4, i64 1
%135 = bitcast double* %134 to <2 x double>*
%136 = load <2 x double>, <2 x double>* %135
%137 = fadd <2 x double> %130, %136
%138 = getelementptr inbounds double, double* %4, i64 3
%139 = load double, double* %138
%140 = insertelement <2 x double> poison, double %133, i64 0
%141 = insertelement <2 x double> %140, double %139, i64 1
%142 = fadd <2 x double> %131, %141
br label %154
143: ; preds = %129
%144 = load double, double* %4
%145 = getelementptr inbounds double, double* %4, i64 1
%146 = bitcast double* %145 to <2 x double>*
%147 = load <2 x double>, <2 x double>* %146
%148 = fsub <2 x double> %147, %130
%149 = getelementptr inbounds double, double* %4, i64 3
%150 = load double, double* %149
%151 = insertelement <2 x double> poison, double %144, i64 0
%152 = insertelement <2 x double> %151, double %150, i64 1
%153 = fsub <2 x double> %152, %131
br label %154
154: ; preds = %129, %143, %132
%155 = phi <2 x double> [ %130, %129 ], [ %137, %132 ], [ %148, %143 ]
%156 = phi <2 x double> [ %131, %129 ], [ %142, %132 ], [ %153, %143 ]
%157 = icmp sgt i32 %0, 3
%158 = extractelement <2 x double> %156, i64 0
store double %158, double* %5
br i1 %157, label %159, label %163
159: ; preds = %154
%160 = getelementptr inbounds double, double* %5, i64 1
%161 = bitcast double* %160 to <2 x double>*
store <2 x double> %155, <2 x double>* %161
%162 = extractelement <2 x double> %156, i64 1
br label %170
163: ; preds = %154
%164 = icmp sgt i32 %0, 1
br i1 %164, label %165, label %174
165: ; preds = %163
%166 = getelementptr inbounds double, double* %5, i64 1
%167 = extractelement <2 x double> %155, i64 0
store double %167, double* %166
%168 = icmp eq i32 %0, 2
%169 = extractelement <2 x double> %155, i64 1
br i1 %168, label %174, label %170
170: ; preds = %165, %159
%171 = phi i64 [ 3, %159 ], [ 2, %165 ]
%172 = phi double [ %162, %159 ], [ %169, %165 ]
%173 = getelementptr inbounds double, double* %5, i64 %171
store double %172, double* %173
br label %174
174: ; preds = %170, %165, %163, %7
ret void
}