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;
  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) {
    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    15cd <kernel_dgemv_n_4_vs_lib4+0x4cd>
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    13c9 <kernel_dgemv_n_4_vs_lib4+0x2c9>
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    115a <kernel_dgemv_n_4_vs_lib4+0x5a>
jmp    13ce <kernel_dgemv_n_4_vs_lib4+0x2ce>
mov    -0x30(%rbp),%eax
cmp    -0x8(%rbp),%eax
jge    148c <kernel_dgemv_n_4_vs_lib4+0x38c>
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    13ce <kernel_dgemv_n_4_vs_lib4+0x2ce>
cmpl   $0x0,0x10(%rbp)
jne    149b <kernel_dgemv_n_4_vs_lib4+0x39b>
jmp    1540 <kernel_dgemv_n_4_vs_lib4+0x440>
cmpl   $0x1,0x10(%rbp)
jne    14f5 <kernel_dgemv_n_4_vs_lib4+0x3f5>
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    1540 <kernel_dgemv_n_4_vs_lib4+0x440>
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     1586 <kernel_dgemv_n_4_vs_lib4+0x486>
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    15cd <kernel_dgemv_n_4_vs_lib4+0x4cd>
movsd  -0x58(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,(%rax)
cmpl   $0x2,-0x4(%rbp)
jl     15c8 <kernel_dgemv_n_4_vs_lib4+0x4c8>
movsd  -0x60(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x8(%rax)
cmpl   $0x2,-0x4(%rbp)
jle    15c3 <kernel_dgemv_n_4_vs_lib4+0x4c3>
movsd  -0x68(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,0x10(%rax)
jmp    15c8 <kernel_dgemv_n_4_vs_lib4+0x4c8>
jmp    15cd <kernel_dgemv_n_4_vs_lib4+0x4cd>
pop    %rbp
ret

x86 assembly (clang, -O2):
<kernel_dgemv_n_4_vs_lib4>:
test   %esi,%esi
jle    12d5 <kernel_dgemv_n_4_vs_lib4+0x1d5>
cmp    $0x4,%esi
jb     11e9 <kernel_dgemv_n_4_vs_lib4+0xe9>
lea    -0x3(%rsi),%r10d
xorpd  %xmm4,%xmm4
xor    %eax,%eax
xorpd  %xmm5,%xmm5
nop
movupd 0x8(%rdx),%xmm1
movsd  (%rcx),%xmm3
movsd  0x8(%rcx),%xmm6
movsd  0x10(%rcx),%xmm0
movsd  0x18(%rcx),%xmm2
unpcklpd %xmm3,%xmm3
mulpd  %xmm3,%xmm1
addpd  %xmm4,%xmm1
movsd  (%rdx),%xmm4
movhpd 0x18(%rdx),%xmm4
mulpd  %xmm3,%xmm4
addpd  %xmm5,%xmm4
movupd 0x28(%rdx),%xmm5
unpcklpd %xmm6,%xmm6
mulpd  %xmm6,%xmm5
addpd  %xmm1,%xmm5
movsd  0x20(%rdx),%xmm1
movhpd 0x38(%rdx),%xmm1
mulpd  %xmm6,%xmm1
addpd  %xmm4,%xmm1
movupd 0x48(%rdx),%xmm3
unpcklpd %xmm0,%xmm0
mulpd  %xmm0,%xmm3
movsd  0x40(%rdx),%xmm6
movhpd 0x58(%rdx),%xmm6
addpd  %xmm5,%xmm3
mulpd  %xmm0,%xmm6
addpd  %xmm1,%xmm6
movupd 0x68(%rdx),%xmm0
unpcklpd %xmm2,%xmm2
mulpd  %xmm2,%xmm0
movapd %xmm0,%xmm4
addpd  %xmm3,%xmm4
movsd  0x60(%rdx),%xmm1
movhpd 0x78(%rdx),%xmm1
mulpd  %xmm2,%xmm1
movapd %xmm1,%xmm5
addpd  %xmm6,%xmm5
sub    $0xffffffffffffff80,%rdx
add    $0x20,%rcx
add    $0x4,%eax
cmp    %r10d,%eax
jl     1120 <kernel_dgemv_n_4_vs_lib4+0x20>
addpd  %xmm6,%xmm1
addpd  %xmm3,%xmm0
mov    %esi,%eax
and    $0xfffffffc,%eax
jmp    11f3 <kernel_dgemv_n_4_vs_lib4+0xf3>
xorpd  %xmm0,%xmm0
xor    %eax,%eax
xorpd  %xmm1,%xmm1
mov    0x8(%rsp),%r10d
cmp    %esi,%eax
jge    1253 <kernel_dgemv_n_4_vs_lib4+0x153>
sub    %eax,%esi
xor    %eax,%eax
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    1200 <kernel_dgemv_n_4_vs_lib4+0x100>
addpd  %xmm3,%xmm5
addpd  %xmm2,%xmm4
movapd %xmm4,%xmm0
movapd %xmm5,%xmm1
test   %r10d,%r10d
je     129a <kernel_dgemv_n_4_vs_lib4+0x19a>
cmp    $0x1,%r10d
jne    1279 <kernel_dgemv_n_4_vs_lib4+0x179>
movupd 0x8(%r8),%xmm2
addpd  %xmm2,%xmm0
movsd  (%r8),%xmm2
movhpd 0x18(%r8),%xmm2
addpd  %xmm2,%xmm1
jmp    129a <kernel_dgemv_n_4_vs_lib4+0x19a>
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     12b5 <kernel_dgemv_n_4_vs_lib4+0x1b5>
movupd %xmm0,0x8(%r9)
unpckhpd %xmm1,%xmm1
mov    $0x3,%eax
jmp    12cf <kernel_dgemv_n_4_vs_lib4+0x1cf>
cmp    $0x2,%edi
jl     12d5 <kernel_dgemv_n_4_vs_lib4+0x1d5>
movlpd %xmm0,0x8(%r9)
je     12d5 <kernel_dgemv_n_4_vs_lib4+0x1d5>
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 %273
28: ; preds = %7
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 %29
29: ; preds = %147, %28
%30 = load i32, i32* %16
%31 = load i32, i32* %9
%32 = sub nsw i32 %31, 3
%33 = icmp slt i32 %30, %32
br i1 %33, label %34, label %150
34: ; preds = %29
%35 = load double*, double** %11
%36 = getelementptr inbounds double, double* %35, i64 0
%37 = load double, double* %36
store double %37, double* %17
%38 = load double*, double** %11
%39 = getelementptr inbounds double, double* %38, i64 1
%40 = load double, double* %39
store double %40, double* %18
%41 = load double*, double** %11
%42 = getelementptr inbounds double, double* %41, i64 2
%43 = load double, double* %42
store double %43, double* %19
%44 = load double*, double** %11
%45 = getelementptr inbounds double, double* %44, i64 3
%46 = load double, double* %45
store double %46, double* %20
%47 = load double*, double** %10
%48 = getelementptr inbounds double, double* %47, i64 0
%49 = load double, double* %48
%50 = load double, double* %17
%51 = load double, double* %21
%52 = call double @llvm.fmuladd.f64(double %49, double %50, double %51)
store double %52, double* %21
%53 = load double*, double** %10
%54 = getelementptr inbounds double, double* %53, i64 1
%55 = load double, double* %54
%56 = load double, double* %17
%57 = load double, double* %22
%58 = call double @llvm.fmuladd.f64(double %55, double %56, double %57)
store double %58, double* %22
%59 = load double*, double** %10
%60 = getelementptr inbounds double, double* %59, i64 2
%61 = load double, double* %60
%62 = load double, double* %17
%63 = load double, double* %23
%64 = call double @llvm.fmuladd.f64(double %61, double %62, double %63)
store double %64, double* %23
%65 = load double*, double** %10
%66 = getelementptr inbounds double, double* %65, i64 3
%67 = load double, double* %66
%68 = load double, double* %17
%69 = load double, double* %24
%70 = call double @llvm.fmuladd.f64(double %67, double %68, double %69)
store double %70, double* %24
%71 = load double*, double** %10
%72 = getelementptr inbounds double, double* %71, i64 4
%73 = load double, double* %72
%74 = load double, double* %18
%75 = load double, double* %21
%76 = call double @llvm.fmuladd.f64(double %73, double %74, double %75)
store double %76, double* %21
%77 = load double*, double** %10
%78 = getelementptr inbounds double, double* %77, i64 5
%79 = load double, double* %78
%80 = load double, double* %18
%81 = load double, double* %22
%82 = call double @llvm.fmuladd.f64(double %79, double %80, double %81)
store double %82, double* %22
%83 = load double*, double** %10
%84 = getelementptr inbounds double, double* %83, i64 6
%85 = load double, double* %84
%86 = load double, double* %18
%87 = load double, double* %23
%88 = call double @llvm.fmuladd.f64(double %85, double %86, double %87)
store double %88, double* %23
%89 = load double*, double** %10
%90 = getelementptr inbounds double, double* %89, i64 7
%91 = load double, double* %90
%92 = load double, double* %18
%93 = load double, double* %24
%94 = call double @llvm.fmuladd.f64(double %91, double %92, double %93)
store double %94, double* %24
%95 = load double*, double** %10
%96 = getelementptr inbounds double, double* %95, i64 8
%97 = load double, double* %96
%98 = load double, double* %19
%99 = load double, double* %21
%100 = call double @llvm.fmuladd.f64(double %97, double %98, double %99)
store double %100, double* %21
%101 = load double*, double** %10
%102 = getelementptr inbounds double, double* %101, i64 9
%103 = load double, double* %102
%104 = load double, double* %19
%105 = load double, double* %22
%106 = call double @llvm.fmuladd.f64(double %103, double %104, double %105)
store double %106, double* %22
%107 = load double*, double** %10
%108 = getelementptr inbounds double, double* %107, i64 10
%109 = load double, double* %108
%110 = load double, double* %19
%111 = load double, double* %23
%112 = call double @llvm.fmuladd.f64(double %109, double %110, double %111)
store double %112, double* %23
%113 = load double*, double** %10
%114 = getelementptr inbounds double, double* %113, i64 11
%115 = load double, double* %114
%116 = load double, double* %19
%117 = load double, double* %24
%118 = call double @llvm.fmuladd.f64(double %115, double %116, double %117)
store double %118, double* %24
%119 = load double*, double** %10
%120 = getelementptr inbounds double, double* %119, i64 12
%121 = load double, double* %120
%122 = load double, double* %20
%123 = load double, double* %21
%124 = call double @llvm.fmuladd.f64(double %121, double %122, double %123)
store double %124, double* %21
%125 = load double*, double** %10
%126 = getelementptr inbounds double, double* %125, i64 13
%127 = load double, double* %126
%128 = load double, double* %20
%129 = load double, double* %22
%130 = call double @llvm.fmuladd.f64(double %127, double %128, double %129)
store double %130, double* %22
%131 = load double*, double** %10
%132 = getelementptr inbounds double, double* %131, i64 14
%133 = load double, double* %132
%134 = load double, double* %20
%135 = load double, double* %23
%136 = call double @llvm.fmuladd.f64(double %133, double %134, double %135)
store double %136, double* %23
%137 = load double*, double** %10
%138 = getelementptr inbounds double, double* %137, i64 15
%139 = load double, double* %138
%140 = load double, double* %20
%141 = load double, double* %24
%142 = call double @llvm.fmuladd.f64(double %139, double %140, double %141)
store double %142, double* %24
%143 = load double*, double** %10
%144 = getelementptr inbounds double, double* %143, i64 16
store double* %144, double** %10
%145 = load double*, double** %11
%146 = getelementptr inbounds double, double* %145, i64 4
store double* %146, double** %11
br label %147
147: ; preds = %34
%148 = load i32, i32* %16
%149 = add nsw i32 %148, 4
store i32 %149, i32* %16
br label %29
150: ; preds = %29
br label %151
151: ; preds = %187, %150
%152 = load i32, i32* %16
%153 = load i32, i32* %9
%154 = icmp slt i32 %152, %153
br i1 %154, label %155, label %190
155: ; preds = %151
%156 = load double*, double** %11
%157 = getelementptr inbounds double, double* %156, i64 0
%158 = load double, double* %157
store double %158, double* %17
%159 = load double*, double** %10
%160 = getelementptr inbounds double, double* %159, i64 0
%161 = load double, double* %160
%162 = load double, double* %17
%163 = load double, double* %21
%164 = call double @llvm.fmuladd.f64(double %161, double %162, double %163)
store double %164, double* %21
%165 = load double*, double** %10
%166 = getelementptr inbounds double, double* %165, i64 1
%167 = load double, double* %166
%168 = load double, double* %17
%169 = load double, double* %22
%170 = call double @llvm.fmuladd.f64(double %167, double %168, double %169)
store double %170, double* %22
%171 = load double*, double** %10
%172 = getelementptr inbounds double, double* %171, i64 2
%173 = load double, double* %172
%174 = load double, double* %17
%175 = load double, double* %23
%176 = call double @llvm.fmuladd.f64(double %173, double %174, double %175)
store double %176, double* %23
%177 = load double*, double** %10
%178 = getelementptr inbounds double, double* %177, i64 3
%179 = load double, double* %178
%180 = load double, double* %17
%181 = load double, double* %24
%182 = call double @llvm.fmuladd.f64(double %179, double %180, double %181)
store double %182, double* %24
%183 = load double*, double** %10
%184 = getelementptr inbounds double, double* %183, i64 4
store double* %184, double** %10
%185 = load double*, double** %11
%186 = getelementptr inbounds double, double* %185, i64 1
store double* %186, double** %11
br label %187
187: ; preds = %155
%188 = load i32, i32* %16
%189 = add nsw i32 %188, 1
store i32 %189, i32* %16
br label %151
190: ; preds = %151
%191 = load i32, i32* %14
%192 = icmp eq i32 %191, 0
br i1 %192, label %193, label %194
193: ; preds = %190
br label %239
194: ; preds = %190
%195 = load i32, i32* %14
%196 = icmp eq i32 %195, 1
br i1 %196, label %197, label %218
197: ; preds = %194
%198 = load double*, double** %12
%199 = getelementptr inbounds double, double* %198, i64 0
%200 = load double, double* %199
%201 = load double, double* %21
%202 = fadd double %201, %200
store double %202, double* %21
%203 = load double*, double** %12
%204 = getelementptr inbounds double, double* %203, i64 1
%205 = load double, double* %204
%206 = load double, double* %22
%207 = fadd double %206, %205
store double %207, double* %22
%208 = load double*, double** %12
%209 = getelementptr inbounds double, double* %208, i64 2
%210 = load double, double* %209
%211 = load double, double* %23
%212 = fadd double %211, %210
store double %212, double* %23
%213 = load double*, double** %12
%214 = getelementptr inbounds double, double* %213, i64 3
%215 = load double, double* %214
%216 = load double, double* %24
%217 = fadd double %216, %215
store double %217, double* %24
br label %239
218: ; preds = %194
%219 = load double*, double** %12
%220 = getelementptr inbounds double, double* %219, i64 0
%221 = load double, double* %220
%222 = load double, double* %21
%223 = fsub double %221, %222
store double %223, double* %21
%224 = load double*, double** %12
%225 = getelementptr inbounds double, double* %224, i64 1
%226 = load double, double* %225
%227 = load double, double* %22
%228 = fsub double %226, %227
store double %228, double* %22
%229 = load double*, double** %12
%230 = getelementptr inbounds double, double* %229, i64 2
%231 = load double, double* %230
%232 = load double, double* %23
%233 = fsub double %231, %232
store double %233, double* %23
%234 = load double*, double** %12
%235 = getelementptr inbounds double, double* %234, i64 3
%236 = load double, double* %235
%237 = load double, double* %24
%238 = fsub double %236, %237
store double %238, double* %24
br label %239
239: ; preds = %218, %197, %193
%240 = load i32, i32* %8
%241 = icmp sge i32 %240, 4
br i1 %241, label %242, label %255
242: ; preds = %239
%243 = load double, double* %21
%244 = load double*, double** %13
%245 = getelementptr inbounds double, double* %244, i64 0
store double %243, double* %245
%246 = load double, double* %22
%247 = load double*, double** %13
%248 = getelementptr inbounds double, double* %247, i64 1
store double %246, double* %248
%249 = load double, double* %23
%250 = load double*, double** %13
%251 = getelementptr inbounds double, double* %250, i64 2
store double %249, double* %251
%252 = load double, double* %24
%253 = load double*, double** %13
%254 = getelementptr inbounds double, double* %253, i64 3
store double %252, double* %254
br label %273
255: ; preds = %239
%256 = load double, double* %21
%257 = load double*, double** %13
%258 = getelementptr inbounds double, double* %257, i64 0
store double %256, double* %258
%259 = load i32, i32* %8
%260 = icmp sge i32 %259, 2
br i1 %260, label %261, label %272
261: ; preds = %255
%262 = load double, double* %22
%263 = load double*, double** %13
%264 = getelementptr inbounds double, double* %263, i64 1
store double %262, double* %264
%265 = load i32, i32* %8
%266 = icmp sgt i32 %265, 2
br i1 %266, label %267, label %271
267: ; preds = %261
%268 = load double, double* %23
%269 = load double*, double** %13
%270 = getelementptr inbounds double, double* %269, i64 2
store double %268, double* %270
br label %271
271: ; preds = %267, %261
br label %272
272: ; preds = %271, %255
br label %273
273: ; preds = %27, %272, %242
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 %168, label %9
9: ; preds = %7
%10 = add nsw i32 %1, -3
%11 = icmp ugt i32 %1, 3
br i1 %11, label %29, label %22
12: ; preds = %29
%13 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %52, <2 x double> %47, <2 x double> %34)
%14 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %65, <2 x double> %60, <2 x double> %13)
%15 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %78, <2 x double> %73, <2 x double> %14)
%16 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %91, <2 x double> %86, <2 x double> %15)
%17 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %45, <2 x double> %47, <2 x double> %33)
%18 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %58, <2 x double> %60, <2 x double> %17)
%19 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %71, <2 x double> %73, <2 x double> %18)
%20 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %84, <2 x double> %86, <2 x double> %19)
%21 = and i32 %1, -4
br label %22
22: ; preds = %12, %9
%23 = phi i32 [ 0, %9 ], [ %21, %12 ]
%24 = phi double* [ %3, %9 ], [ %94, %12 ]
%25 = phi double* [ %2, %9 ], [ %93, %12 ]
%26 = phi <2 x double> [ zeroinitializer, %9 ], [ %20, %12 ]
%27 = phi <2 x double> [ zeroinitializer, %9 ], [ %16, %12 ]
%28 = icmp slt i32 %23, %1
br i1 %28, label %97, label %123
29: ; preds = %9, %29
%30 = phi double* [ %93, %29 ], [ %2, %9 ]
%31 = phi double* [ %94, %29 ], [ %3, %9 ]
%32 = phi i32 [ %95, %29 ], [ 0, %9 ]
%33 = phi <2 x double> [ %87, %29 ], [ zeroinitializer, %9 ]
%34 = phi <2 x double> [ %92, %29 ], [ zeroinitializer, %9 ]
%35 = load double, double* %31
%36 = getelementptr inbounds double, double* %31, i64 1
%37 = load double, double* %36
%38 = getelementptr inbounds double, double* %31, i64 2
%39 = load double, double* %38
%40 = getelementptr inbounds double, double* %31, i64 3
%41 = load double, double* %40
%42 = load double, double* %30
%43 = getelementptr inbounds double, double* %30, i64 1
%44 = bitcast double* %43 to <2 x double>*
%45 = load <2 x double>, <2 x double>* %44
%46 = insertelement <2 x double> poison, double %35, i64 0
%47 = shufflevector <2 x double> %46, <2 x double> poison, <2 x i32> zeroinitializer
%48 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %45, <2 x double> %47, <2 x double> %33)
%49 = getelementptr inbounds double, double* %30, i64 3
%50 = load double, double* %49
%51 = insertelement <2 x double> poison, double %42, i64 0
%52 = insertelement <2 x double> %51, double %50, i64 1
%53 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %52, <2 x double> %47, <2 x double> %34)
%54 = getelementptr inbounds double, double* %30, i64 4
%55 = load double, double* %54
%56 = getelementptr inbounds double, double* %30, i64 5
%57 = bitcast double* %56 to <2 x double>*
%58 = load <2 x double>, <2 x double>* %57
%59 = insertelement <2 x double> poison, double %37, i64 0
%60 = shufflevector <2 x double> %59, <2 x double> poison, <2 x i32> zeroinitializer
%61 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %58, <2 x double> %60, <2 x double> %48)
%62 = getelementptr inbounds double, double* %30, i64 7
%63 = load double, double* %62
%64 = insertelement <2 x double> poison, double %55, i64 0
%65 = insertelement <2 x double> %64, double %63, i64 1
%66 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %65, <2 x double> %60, <2 x double> %53)
%67 = getelementptr inbounds double, double* %30, i64 8
%68 = load double, double* %67
%69 = getelementptr inbounds double, double* %30, i64 9
%70 = bitcast double* %69 to <2 x double>*
%71 = load <2 x double>, <2 x double>* %70
%72 = insertelement <2 x double> poison, double %39, i64 0
%73 = shufflevector <2 x double> %72, <2 x double> poison, <2 x i32> zeroinitializer
%74 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %71, <2 x double> %73, <2 x double> %61)
%75 = getelementptr inbounds double, double* %30, i64 11
%76 = load double, double* %75
%77 = insertelement <2 x double> poison, double %68, i64 0
%78 = insertelement <2 x double> %77, double %76, i64 1
%79 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %78, <2 x double> %73, <2 x double> %66)
%80 = getelementptr inbounds double, double* %30, i64 12
%81 = load double, double* %80
%82 = getelementptr inbounds double, double* %30, i64 13
%83 = bitcast double* %82 to <2 x double>*
%84 = load <2 x double>, <2 x double>* %83
%85 = insertelement <2 x double> poison, double %41, i64 0
%86 = shufflevector <2 x double> %85, <2 x double> poison, <2 x i32> zeroinitializer
%87 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %84, <2 x double> %86, <2 x double> %74)
%88 = getelementptr inbounds double, double* %30, i64 15
%89 = load double, double* %88
%90 = insertelement <2 x double> poison, double %81, i64 0
%91 = insertelement <2 x double> %90, double %89, i64 1
%92 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %91, <2 x double> %86, <2 x double> %79)
%93 = getelementptr inbounds double, double* %30, i64 16
%94 = getelementptr inbounds double, double* %31, i64 4
%95 = add nuw nsw i32 %32, 4
%96 = icmp slt i32 %95, %10
br i1 %96, label %29, label %12
97: ; preds = %22, %97
%98 = phi double* [ %116, %97 ], [ %25, %22 ]
%99 = phi double* [ %117, %97 ], [ %24, %22 ]
%100 = phi i32 [ %118, %97 ], [ %23, %22 ]
%101 = phi <2 x double> [ %110, %97 ], [ %26, %22 ]
%102 = phi <2 x double> [ %115, %97 ], [ %27, %22 ]
%103 = load double, double* %99
%104 = load double, double* %98
%105 = getelementptr inbounds double, double* %98, i64 1
%106 = bitcast double* %105 to <2 x double>*
%107 = load <2 x double>, <2 x double>* %106
%108 = insertelement <2 x double> poison, double %103, i64 0
%109 = shufflevector <2 x double> %108, <2 x double> poison, <2 x i32> zeroinitializer
%110 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %107, <2 x double> %109, <2 x double> %101)
%111 = getelementptr inbounds double, double* %98, i64 3
%112 = load double, double* %111
%113 = insertelement <2 x double> poison, double %104, i64 0
%114 = insertelement <2 x double> %113, double %112, i64 1
%115 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %114, <2 x double> %109, <2 x double> %102)
%116 = getelementptr inbounds double, double* %98, i64 4
%117 = getelementptr inbounds double, double* %99, i64 1
%118 = add nuw nsw i32 %100, 1
%119 = icmp eq i32 %118, %1
br i1 %119, label %120, label %97
120: ; preds = %97
%121 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %114, <2 x double> %109, <2 x double> %102)
%122 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %107, <2 x double> %109, <2 x double> %101)
br label %123
123: ; preds = %120, %22
%124 = phi <2 x double> [ %26, %22 ], [ %122, %120 ]
%125 = phi <2 x double> [ %27, %22 ], [ %121, %120 ]
switch i32 %6, label %137 [
i32 0, label %148
i32 1, label %126
]
126: ; preds = %123
%127 = load double, double* %4
%128 = getelementptr inbounds double, double* %4, i64 1
%129 = bitcast double* %128 to <2 x double>*
%130 = load <2 x double>, <2 x double>* %129
%131 = fadd <2 x double> %124, %130
%132 = getelementptr inbounds double, double* %4, i64 3
%133 = load double, double* %132
%134 = insertelement <2 x double> poison, double %127, i64 0
%135 = insertelement <2 x double> %134, double %133, i64 1
%136 = fadd <2 x double> %125, %135
br label %148
137: ; preds = %123
%138 = load double, double* %4
%139 = getelementptr inbounds double, double* %4, i64 1
%140 = bitcast double* %139 to <2 x double>*
%141 = load <2 x double>, <2 x double>* %140
%142 = fsub <2 x double> %141, %124
%143 = getelementptr inbounds double, double* %4, i64 3
%144 = load double, double* %143
%145 = insertelement <2 x double> poison, double %138, i64 0
%146 = insertelement <2 x double> %145, double %144, i64 1
%147 = fsub <2 x double> %146, %125
br label %148
148: ; preds = %123, %137, %126
%149 = phi <2 x double> [ %124, %123 ], [ %131, %126 ], [ %142, %137 ]
%150 = phi <2 x double> [ %125, %123 ], [ %136, %126 ], [ %147, %137 ]
%151 = icmp sgt i32 %0, 3
%152 = extractelement <2 x double> %150, i64 0
store double %152, double* %5
br i1 %151, label %153, label %157
153: ; preds = %148
%154 = getelementptr inbounds double, double* %5, i64 1
%155 = bitcast double* %154 to <2 x double>*
store <2 x double> %149, <2 x double>* %155
%156 = extractelement <2 x double> %150, i64 1
br label %164
157: ; preds = %148
%158 = icmp sgt i32 %0, 1
br i1 %158, label %159, label %168
159: ; preds = %157
%160 = getelementptr inbounds double, double* %5, i64 1
%161 = extractelement <2 x double> %149, i64 0
store double %161, double* %160
%162 = icmp eq i32 %0, 2
%163 = extractelement <2 x double> %149, i64 1
br i1 %162, label %168, label %164
164: ; preds = %159, %153
%165 = phi i64 [ 3, %153 ], [ 2, %159 ]
%166 = phi double [ %156, %153 ], [ %163, %159 ]
%167 = getelementptr inbounds double, double* %5, i64 %165
store double %166, double* %167
br label %168
168: ; preds = %164, %159, %157, %7
ret void
}