Files
OpenBLAS/kernel/riscv64/dgemm_kernel_8x8_zvl256b.c

1747 lines
63 KiB
C

/*
AUTOGENERATED KERNEL
Settings:
LMUL=1
M=8
M_tail_scalar_from=2
N=8
__riscv_='__riscv_'
complex=False
conjugate=False
cpu='zvl256b'
force_acc_double=False
index_type='BLASLONG'
op='gemm'
param_precision='double'
reg_width_bits=256
tail_policy=''
trace=False
Derived:
ELEN_ACC=64
ELEN_PARAM=64
LMUL_ACC=1
VFMACC='__riscv_vfmacc_vf_f64m1'
VFMUL='__riscv_vfmul_vf_f64m1'
VLEV='__riscv_vle64_v_f64m1'
VLSEV='__riscv_vlse64_v_f64m1'
VMACC_TO_ACC='__riscv_vfmacc_vf_f64m1'
VMUL_TO_ACC='__riscv_vfmul_vf_f64m1'
VSETVL='__riscv_vsetvl_e64m1'
VSEV='__riscv_vse64_v_f64m1'
VSSEV='__riscv_vsse64_v_f64m1'
acc_vector_t='vfloat64m1_t'
output='dgemm_kernel_8x8_zvl256b.c'
param_scalar_t='double'
param_vector_t='vfloat64m1_t'
*/
#include "common.h"
#include <stdbool.h>
#define GEMM_RIGHT_EDGE // One pass for right edge - swap A & B - transpose at end
#define GEMM_BOTTOM_EDGE // One pass for bottom edge - combo on vector and scalar ops
#define GEMM_RIGHT_CHUNK // Break K into chunks (causes epsilon differences)
#define GEMM_BOTTOM_CHUNK // Break K into chunks (causes epsilon differences)
//#define GEMM_NEW_PACKING // Right edge packed data friendly
#define FORCEINLINE inline __attribute__((always_inline))
#ifdef GEMM_NEW_PACKING
static FORCEINLINE FLOAT* M_TAIL_ONE(BLASLONG K, const BLASLONG M, const BLASLONG N, const bool S, FLOAT alpha, FLOAT* A0, FLOAT*, FLOAT*, FLOAT* B, FLOAT* C, BLASLONG ldc)
#else
static FORCEINLINE FLOAT* M_TAIL_ONE(BLASLONG K, const BLASLONG M, const BLASLONG N, const bool S, FLOAT alpha, FLOAT* A0, FLOAT* A1, FLOAT* A2, FLOAT* B, FLOAT* C, BLASLONG ldc)
#endif
{
if (N & 8) {
vfloat64m2_t result0, result2, result4, result6, result8, resultA, resultC;
vfloat64m2_t B0;
FLOAT A00, A01, A02, A03, A04, A05, A06;
#ifdef GEMM_RIGHT_CHUNK
vfloat64m2_t resultE;
vfloat64m2_t B2, B4, B6;
FLOAT A07;
if (M == 1) {
if (K >= 8) {
vfloat64m8_t B00 = __riscv_vle64_v_f64m8(B, N * 4);
B += (N * 4);
B0 = __riscv_vget_v_f64m8_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m8_f64m2(B00, 1);
B4 = __riscv_vget_v_f64m8_f64m2(B00, 2);
B6 = __riscv_vget_v_f64m8_f64m2(B00, 3);
#ifdef GEMM_NEW_PACKING
A00 = A0[0 + (1 * 0)];
A01 = A0[0 + (1 * 1)];
A02 = A0[0 + (1 * 2)];
A03 = A0[0 + (1 * 3)];
A04 = A0[0 + (1 * 4)];
A05 = A0[0 + (1 * 5)];
A06 = A0[0 + (1 * 6)];
A07 = A0[0 + (1 * 7)];
A0 += (1 * 8);
#else
A00 = A2[0 + (1 * 0)];
A01 = A2[0 + (1 * 1)];
A02 = A2[0 + (1 * 2)];
A03 = A2[0 + (1 * 3)];
A04 = A2[0 + (1 * 4)];
A05 = A2[0 + (1 * 5)];
A06 = A2[0 + (1 * 6)];
A07 = A2[0 + (1 * 7)];
A2 += (1 * 8);
#endif
resultC = __riscv_vfmul_vf_f64m2(B0, A00, 8);
result0 = __riscv_vfmul_vf_f64m2(B2, A01, 8);
result2 = __riscv_vfmul_vf_f64m2(B4, A02, 8);
result4 = __riscv_vfmul_vf_f64m2(B6, A03, 8);
B00 = __riscv_vle64_v_f64m8(B, N * 4);
B += (N * 4);
B0 = __riscv_vget_v_f64m8_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m8_f64m2(B00, 1);
B4 = __riscv_vget_v_f64m8_f64m2(B00, 2);
B6 = __riscv_vget_v_f64m8_f64m2(B00, 3);
result6 = __riscv_vfmul_vf_f64m2(B0, A04, 8);
result8 = __riscv_vfmul_vf_f64m2(B2, A05, 8);
resultA = __riscv_vfmul_vf_f64m2(B4, A06, 8);
resultE = __riscv_vfmul_vf_f64m2(B6, A07, 8);
BLASLONG k = (K / 8);
K &= 7;
while (--k) {
B00 = __riscv_vle64_v_f64m8(B, N * 4);
B += (N * 4);
B0 = __riscv_vget_v_f64m8_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m8_f64m2(B00, 1);
B4 = __riscv_vget_v_f64m8_f64m2(B00, 2);
B6 = __riscv_vget_v_f64m8_f64m2(B00, 3);
#ifdef GEMM_NEW_PACKING
A00 = A0[0 + (1 * 0)];
A01 = A0[0 + (1 * 1)];
A02 = A0[0 + (1 * 2)];
A03 = A0[0 + (1 * 3)];
A04 = A0[0 + (1 * 4)];
A05 = A0[0 + (1 * 5)];
A06 = A0[0 + (1 * 6)];
A07 = A0[0 + (1 * 7)];
A0 += (1 * 8);
#else
A00 = A2[0 + (1 * 0)];
A01 = A2[0 + (1 * 1)];
A02 = A2[0 + (1 * 2)];
A03 = A2[0 + (1 * 3)];
A04 = A2[0 + (1 * 4)];
A05 = A2[0 + (1 * 5)];
A06 = A2[0 + (1 * 6)];
A07 = A2[0 + (1 * 7)];
A2 += (1 * 8);
#endif
resultC = __riscv_vfmacc_vf_f64m2(resultC, A00, B0, 8);
result0 = __riscv_vfmacc_vf_f64m2(result0, A01, B2, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, A02, B4, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, A03, B6, 8);
B00 = __riscv_vle64_v_f64m8(B, N * 4);
B += (N * 4);
B0 = __riscv_vget_v_f64m8_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m8_f64m2(B00, 1);
B4 = __riscv_vget_v_f64m8_f64m2(B00, 2);
B6 = __riscv_vget_v_f64m8_f64m2(B00, 3);
result6 = __riscv_vfmacc_vf_f64m2(result6, A04, B0, 8);
result8 = __riscv_vfmacc_vf_f64m2(result8, A05, B2, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, A06, B4, 8);
resultE = __riscv_vfmacc_vf_f64m2(resultE, A07, B6, 8);
}
resultC = __riscv_vfadd_vv_f64m2(resultC, result6, 8);
result0 = __riscv_vfadd_vv_f64m2(result0, result8, 8);
result2 = __riscv_vfadd_vv_f64m2(result2, resultA, 8);
result4 = __riscv_vfadd_vv_f64m2(result4, resultE, 8);
resultC = __riscv_vfadd_vv_f64m2(resultC, result0, 8);
result2 = __riscv_vfadd_vv_f64m2(result2, result4, 8);
resultC = __riscv_vfadd_vv_f64m2(resultC, result2, 8);
} else {
resultC = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
}
} else if (M == 2) {
if (K >= 4) {
vfloat64m8_t B00 = __riscv_vle64_v_f64m8(B, N * 4);
B += (N * 4);
B0 = __riscv_vget_v_f64m8_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m8_f64m2(B00, 1);
B4 = __riscv_vget_v_f64m8_f64m2(B00, 2);
B6 = __riscv_vget_v_f64m8_f64m2(B00, 3);
#ifdef GEMM_NEW_PACKING
A00 = A0[0 + (2 * 0)];
A01 = A0[1 + (2 * 0)];
A02 = A0[0 + (2 * 1)];
A03 = A0[1 + (2 * 1)];
A04 = A0[0 + (2 * 2)];
A05 = A0[1 + (2 * 2)];
A06 = A0[0 + (2 * 3)];
A07 = A0[1 + (2 * 3)];
A0 += (2 * 4);
#else
A00 = A1[0 + (2 * 0)];
A01 = A1[1 + (2 * 0)];
A02 = A1[0 + (2 * 1)];
A03 = A1[1 + (2 * 1)];
A04 = A1[0 + (2 * 2)];
A05 = A1[1 + (2 * 2)];
A06 = A1[0 + (2 * 3)];
A07 = A1[1 + (2 * 3)];
A1 += (2 * 4);
#endif
result8 = __riscv_vfmul_vf_f64m2(B0, A00, 8);
resultA = __riscv_vfmul_vf_f64m2(B0, A01, 8);
result0 = __riscv_vfmul_vf_f64m2(B2, A02, 8);
result2 = __riscv_vfmul_vf_f64m2(B2, A03, 8);
result4 = __riscv_vfmul_vf_f64m2(B4, A04, 8);
result6 = __riscv_vfmul_vf_f64m2(B4, A05, 8);
resultC = __riscv_vfmul_vf_f64m2(B6, A06, 8);
resultE = __riscv_vfmul_vf_f64m2(B6, A07, 8);
BLASLONG k = (K / 4);
K &= 3;
while (--k) {
B00 = __riscv_vle64_v_f64m8(B, N * 4);
B += (N * 4);
B0 = __riscv_vget_v_f64m8_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m8_f64m2(B00, 1);
B4 = __riscv_vget_v_f64m8_f64m2(B00, 2);
B6 = __riscv_vget_v_f64m8_f64m2(B00, 3);
#ifdef GEMM_NEW_PACKING
A00 = A0[0 + (2 * 0)];
A01 = A0[1 + (2 * 0)];
A02 = A0[0 + (2 * 1)];
A03 = A0[1 + (2 * 1)];
A04 = A0[0 + (2 * 2)];
A05 = A0[1 + (2 * 2)];
A06 = A0[0 + (2 * 3)];
A07 = A0[1 + (2 * 3)];
A0 += (2 * 4);
#else
A00 = A1[0 + (2 * 0)];
A01 = A1[1 + (2 * 0)];
A02 = A1[0 + (2 * 1)];
A03 = A1[1 + (2 * 1)];
A04 = A1[0 + (2 * 2)];
A05 = A1[1 + (2 * 2)];
A06 = A1[0 + (2 * 3)];
A07 = A1[1 + (2 * 3)];
A1 += (2 * 4);
#endif
result8 = __riscv_vfmacc_vf_f64m2(result8, A00, B0, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, A01, B0, 8);
result0 = __riscv_vfmacc_vf_f64m2(result0, A02, B2, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, A03, B2, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, A04, B4, 8);
result6 = __riscv_vfmacc_vf_f64m2(result6, A05, B4, 8);
resultC = __riscv_vfmacc_vf_f64m2(resultC, A06, B6, 8);
resultE = __riscv_vfmacc_vf_f64m2(resultE, A07, B6, 8);
}
result8 = __riscv_vfadd_vv_f64m2(result8, result0, 8);
resultA = __riscv_vfadd_vv_f64m2(resultA, result2, 8);
result4 = __riscv_vfadd_vv_f64m2(result4, resultC, 8);
result6 = __riscv_vfadd_vv_f64m2(result6, resultE, 8);
result8 = __riscv_vfadd_vv_f64m2(result8, result4, 8);
resultA = __riscv_vfadd_vv_f64m2(resultA, result6, 8);
} else {
result8 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
resultA = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
}
} else if (M <= 4) {
if (K >= 2) {
vfloat64m4_t B00 = __riscv_vle64_v_f64m4(B, N * 2);
B += (N * 2);
B0 = __riscv_vget_v_f64m4_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m4_f64m2(B00, 1);
if (M & 4) {
A00 = A0[0];
A01 = A0[1];
A02 = A0[2];
A03 = A0[3];
A04 = A0[4];
A05 = A0[5];
A06 = A0[6];
A07 = A0[7];
#ifndef GEMM_NEW_PACKING
A0 += 8;
#endif
}
#ifdef GEMM_NEW_PACKING
if (M & 2) {
A00 = A0[0 + (M * 0)];
A01 = A0[1 + (M * 0)];
A02 = A0[0 + (M * 1)];
A03 = A0[1 + (M * 1)];
}
if (M & 1) {
A04 = A0[2 + (M * 0)];
A05 = A0[2 + (M * 1)];
}
A0 += (M * 2);
#else
if (M & 2) {
A00 = A1[0 + (2 * 0)];
A01 = A1[1 + (2 * 0)];
A02 = A1[0 + (2 * 1)];
A03 = A1[1 + (2 * 1)];
A1 += (2 * 2);
}
if (M & 1) {
A04 = A2[0 + (1 * 0)];
A05 = A2[0 + (1 * 1)];
A2 += (1 * 2);
}
#endif
if (M & 4) {
result0 = __riscv_vfmul_vf_f64m2(B0, A00, 8);
result2 = __riscv_vfmul_vf_f64m2(B0, A01, 8);
result4 = __riscv_vfmul_vf_f64m2(B0, A02, 8);
result6 = __riscv_vfmul_vf_f64m2(B0, A03, 8);
result8 = __riscv_vfmul_vf_f64m2(B2, A04, 8);
resultA = __riscv_vfmul_vf_f64m2(B2, A05, 8);
resultC = __riscv_vfmul_vf_f64m2(B2, A06, 8);
resultE = __riscv_vfmul_vf_f64m2(B2, A07, 8);
} else {
result8 = __riscv_vfmul_vf_f64m2(B0, A00, 8);
resultA = __riscv_vfmul_vf_f64m2(B0, A01, 8);
result0 = __riscv_vfmul_vf_f64m2(B2, A02, 8);
result2 = __riscv_vfmul_vf_f64m2(B2, A03, 8);
resultC = __riscv_vfmul_vf_f64m2(B0, A04, 8);
result4 = __riscv_vfmul_vf_f64m2(B2, A05, 8);
}
BLASLONG k = (K / 2);
K &= 1;
while (--k) {
B00 = __riscv_vle64_v_f64m4(B, N * 2);
B += (N * 2);
B0 = __riscv_vget_v_f64m4_f64m2(B00, 0);
B2 = __riscv_vget_v_f64m4_f64m2(B00, 1);
if (M & 4) {
A00 = A0[0];
A01 = A0[1];
A02 = A0[2];
A03 = A0[3];
A04 = A0[4];
A05 = A0[5];
A06 = A0[6];
A07 = A0[7];
#ifndef GEMM_NEW_PACKING
A0 += 8;
#endif
}
#ifdef GEMM_NEW_PACKING
if (M & 2) {
A00 = A0[0 + (M * 0)];
A01 = A0[1 + (M * 0)];
A02 = A0[0 + (M * 1)];
A03 = A0[1 + (M * 1)];
}
if (M & 1) {
A04 = A0[2 + (M * 0)];
A05 = A0[2 + (M * 1)];
}
A0 += (M * 2);
#else
if (M & 2) {
A00 = A1[0 + (2 * 0)];
A01 = A1[1 + (2 * 0)];
A02 = A1[0 + (2 * 1)];
A03 = A1[1 + (2 * 1)];
A1 += (2 * 2);
}
if (M & 1) {
A04 = A2[0 + (1 * 0)];
A05 = A2[0 + (1 * 1)];
A2 += (1 * 2);
}
#endif
if (M & 4) {
result0 = __riscv_vfmacc_vf_f64m2(result0, A00, B0, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, A01, B0, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, A02, B0, 8);
result6 = __riscv_vfmacc_vf_f64m2(result6, A03, B0, 8);
result8 = __riscv_vfmacc_vf_f64m2(result8, A04, B2, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, A05, B2, 8);
resultC = __riscv_vfmacc_vf_f64m2(resultC, A06, B2, 8);
resultE = __riscv_vfmacc_vf_f64m2(resultE, A07, B2, 8);
} else {
result8 = __riscv_vfmacc_vf_f64m2(result8, A00, B0, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, A01, B0, 8);
result0 = __riscv_vfmacc_vf_f64m2(result0, A02, B2, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, A03, B2, 8);
resultC = __riscv_vfmacc_vf_f64m2(resultC, A04, B0, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, A05, B2, 8);
}
}
if (M & 4) {
result0 = __riscv_vfadd_vv_f64m2(result0, result8, 8);
result2 = __riscv_vfadd_vv_f64m2(result2, resultA, 8);
result4 = __riscv_vfadd_vv_f64m2(result4, resultC, 8);
result6 = __riscv_vfadd_vv_f64m2(result6, resultE, 8);
} else {
result8 = __riscv_vfadd_vv_f64m2(result8, result0, 8);
resultA = __riscv_vfadd_vv_f64m2(resultA, result2, 8);
resultC = __riscv_vfadd_vv_f64m2(resultC, result4, 8);
}
} else {
if (M & 4) {
result0 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
result2 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
result4 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
result6 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
} else {
result8 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
resultA = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
resultC = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
}
}
} else
#endif
{
B0 = __riscv_vle64_v_f64m2(B, N);
if (M & 4) {
A00 = A0[0];
A01 = A0[1];
A02 = A0[2];
A03 = A0[3];
#ifndef GEMM_NEW_PACKING
A0 += 4;
#endif
}
B += N;
#ifdef GEMM_NEW_PACKING
if (M & 2) {
A04 = A0[0 + (M & 0x4)];
A05 = A0[1 + (M & 0x4)];
}
if (M & 1) {
A06 = A0[0 + (M & 0x6)];
}
A0 += M;
#else
if (M & 2) {
A04 = A1[0];
A05 = A1[1];
A1 += 2;
}
if (M & 1) {
A06 = A2[0];
A2 += 1;
}
#endif
if (M & 4) {
result0 = __riscv_vfmul_vf_f64m2(B0, A00, 8);
result2 = __riscv_vfmul_vf_f64m2(B0, A01, 8);
result4 = __riscv_vfmul_vf_f64m2(B0, A02, 8);
result6 = __riscv_vfmul_vf_f64m2(B0, A03, 8);
}
if (M & 2) {
result8 = __riscv_vfmul_vf_f64m2(B0, A04, 8);
resultA = __riscv_vfmul_vf_f64m2(B0, A05, 8);
}
if (M & 1) {
resultC = __riscv_vfmul_vf_f64m2(B0, A06, 8);
}
K--;
}
while (K--) {
B0 = __riscv_vle64_v_f64m2(B, N);
if (M & 4) {
A00 = A0[0];
A01 = A0[1];
A02 = A0[2];
A03 = A0[3];
#ifndef GEMM_NEW_PACKING
A0 += 4;
#endif
}
B += N;
#ifdef GEMM_NEW_PACKING
if (M & 2) {
A04 = A0[0 + (M & 0x4)];
A05 = A0[1 + (M & 0x4)];
}
if (M & 1) {
A06 = A0[0 + (M & 0x6)];
}
A0 += M;
#else
if (M & 2) {
A04 = A1[0];
A05 = A1[1];
A1 += 2;
}
if (M & 1) {
A06 = A2[0];
A2 += 1;
}
#endif
if (M & 4) {
result0 = __riscv_vfmacc_vf_f64m2(result0, A00, B0, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, A01, B0, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, A02, B0, 8);
result6 = __riscv_vfmacc_vf_f64m2(result6, A03, B0, 8);
}
if (M & 2) {
result8 = __riscv_vfmacc_vf_f64m2(result8, A04, B0, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, A05, B0, 8);
}
if (M & 1) {
resultC = __riscv_vfmacc_vf_f64m2(resultC, A06, B0, 8);
}
}
if (M & 4) {
vfloat64m2x4_t c14 = __riscv_vlsseg4e64_v_f64m2x4(C, ldc * sizeof(FLOAT), 8);
c14 = __riscv_vset_v_f64m2_f64m2x4(c14, 0, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x4_f64m2(c14, 0), alpha, result0, 8));
c14 = __riscv_vset_v_f64m2_f64m2x4(c14, 1, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x4_f64m2(c14, 1), alpha, result2, 8));
c14 = __riscv_vset_v_f64m2_f64m2x4(c14, 2, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x4_f64m2(c14, 2), alpha, result4, 8));
c14 = __riscv_vset_v_f64m2_f64m2x4(c14, 3, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x4_f64m2(c14, 3), alpha, result6, 8));
__riscv_vssseg4e64_v_f64m2x4(C, ldc * sizeof(FLOAT), c14, 8);
if (M & 3) {
C += 4;
}
}
if ((M & 3) == 1) {
vfloat64m2_t cC;
if (S) {
cC = __riscv_vle64_v_f64m2(C, 8);
} else {
cC = __riscv_vlse64_v_f64m2(C, ldc * sizeof(FLOAT), 8);
}
cC = __riscv_vfmacc_vf_f64m2(cC, alpha, resultC, 8);
if (S) {
__riscv_vse64_v_f64m2(C, cC, 8);
} else {
__riscv_vsse64_v_f64m2(C, ldc * sizeof(FLOAT), cC, 8);
}
} else if ((M & 3) == 2) {
vfloat64m2x2_t c12;
if (S) {
c12 = __riscv_vlseg2e64_v_f64m2x2(C, 8);
} else {
c12 = __riscv_vlsseg2e64_v_f64m2x2(C, ldc * sizeof(FLOAT), 8);
}
c12 = __riscv_vset_v_f64m2_f64m2x2(c12, 0, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x2_f64m2(c12, 0), alpha, result8, 8));
c12 = __riscv_vset_v_f64m2_f64m2x2(c12, 1, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x2_f64m2(c12, 1), alpha, resultA, 8));
if (S) {
__riscv_vsseg2e64_v_f64m2x2(C, c12, 8);
} else {
__riscv_vssseg2e64_v_f64m2x2(C, ldc * sizeof(FLOAT), c12, 8);
}
} else if ((M & 3) == 3) {
vfloat64m2x3_t c13;
if (S) {
c13 = __riscv_vlseg3e64_v_f64m2x3(C, 8);
} else {
c13 = __riscv_vlsseg3e64_v_f64m2x3(C, ldc * sizeof(FLOAT), 8);
}
c13 = __riscv_vset_v_f64m2_f64m2x3(c13, 0, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x3_f64m2(c13, 0), alpha, result8, 8));
c13 = __riscv_vset_v_f64m2_f64m2x3(c13, 1, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x3_f64m2(c13, 1), alpha, resultA, 8));
c13 = __riscv_vset_v_f64m2_f64m2x3(c13, 2, __riscv_vfmacc_vf_f64m2(__riscv_vget_v_f64m2x3_f64m2(c13, 2), alpha, resultC, 8));
if (S) {
__riscv_vsseg3e64_v_f64m2x3(C, c13, 8);
} else {
__riscv_vssseg3e64_v_f64m2x3(C, ldc * sizeof(FLOAT), c13, 8);
}
}
} else {
vfloat64m1_t result0, result2, result4, result6, result8, resultA, resultC, resultE;
vfloat64m1_t result04, result05, result06, result07;
FLOAT r0, r1, r2, r8, r9, rA, rC, rD, rE, a0, a1, a2;
FLOAT B0, B1, B2;
#ifndef GEMM_NEW_PACKING
FLOAT *B00, *B01;
#endif
// Can write better code for GEMM_NEW_PACKING in which N > 4
if (N & 4) {
resultE = __riscv_vle64_v_f64m1(B, 4);
if (M & 4) {
result0 = __riscv_vfmul_vf_f64m1(resultE, A0[0], 4);
result2 = __riscv_vfmul_vf_f64m1(resultE, A0[1], 4);
result4 = __riscv_vfmul_vf_f64m1(resultE, A0[2], 4);
result6 = __riscv_vfmul_vf_f64m1(resultE, A0[3], 4);
}
#ifdef GEMM_NEW_PACKING
if (M & 2) {
result8 = __riscv_vfmul_vf_f64m1(resultE, A0[0 + (M & 0x4)], 4);
resultA = __riscv_vfmul_vf_f64m1(resultE, A0[1 + (M & 0x4)], 4);
}
if (M & 1) {
resultC = __riscv_vfmul_vf_f64m1(resultE, A0[0 + (M & 0x6)], 4);
}
#else
if (M & 2) {
result8 = __riscv_vfmul_vf_f64m1(resultE, A1[0], 4);
resultA = __riscv_vfmul_vf_f64m1(resultE, A1[1], 4);
}
if (M & 1) {
resultC = __riscv_vfmul_vf_f64m1(resultE, A2[0], 4);
}
#endif
}
if (N & 3) {
#ifdef GEMM_NEW_PACKING
if (N & 1) {
B0 = B[0 + (N & 6)];
}
if (N & 2) {
B1 = B[0 + (N & 4)];
B2 = B[1 + (N & 4)];
}
#else
if (N & 1) {
B00 = B + ((N & 6) * K);
B0 = B00[0];
B00 += 1;
}
if (N & 2) {
B01 = B + ((N & 4) * K);
B1 = B01[0];
B2 = B01[1];
B01 += 2;
}
#endif
if (M & 4) {
result04 = __riscv_vle64_v_f64m1(A0, 4);
if (N & 1) {
result05 = __riscv_vfmul_vf_f64m1(result04, B0, 4);
}
if (N & 2) {
result06 = __riscv_vfmul_vf_f64m1(result04, B1, 4);
result07 = __riscv_vfmul_vf_f64m1(result04, B2, 4);
}
}
if (M & 2) {
#ifdef GEMM_NEW_PACKING
a0 = A0[0 + (M & 0x4)];
a1 = A0[1 + (M & 0x4)];
#else
a0 = A1[0];
a1 = A1[1];
#endif
if (N & 1) {
r0 = B0 * a0;
r1 = B0 * a1;
}
if (N & 2) {
r8 = B1 * a0;
r9 = B1 * a1;
rC = B2 * a0;
rD = B2 * a1;
}
}
if (M & 1) {
#ifdef GEMM_NEW_PACKING
a2 = A0[0 + (M & 0x6)];
#else
a2 = A2[0];
#endif
if (N & 1) {
r2 = B0 * a2;
}
if (N & 2) {
rA = B1 * a2;
rE = B2 * a2;
}
}
}
#ifdef GEMM_NEW_PACKING
A0 += M;
B += N;
#else
if (M & 4) {
A0 += 4;
}
if (M & 2) {
A1 += 2;
}
if (M & 1) {
A2 += 1;
}
if (N & 4) {
B += 4;
}
#endif
while (--K) {
if (N & 4) {
resultE = __riscv_vle64_v_f64m1(B, 4);
if (M & 4) {
result0 = __riscv_vfmacc_vf_f64m1(result0, A0[0], resultE, 4);
result2 = __riscv_vfmacc_vf_f64m1(result2, A0[1], resultE, 4);
result4 = __riscv_vfmacc_vf_f64m1(result4, A0[2], resultE, 4);
result6 = __riscv_vfmacc_vf_f64m1(result6, A0[3], resultE, 4);
}
#ifdef GEMM_NEW_PACKING
if (M & 2) {
result8 = __riscv_vfmacc_vf_f64m1(result8, A0[0 + (M & 0x4)], resultE, 4);
resultA = __riscv_vfmacc_vf_f64m1(resultA, A0[1 + (M & 0x4)], resultE, 4);
}
if (M & 1) {
resultC = __riscv_vfmacc_vf_f64m1(resultC, A0[0 + (M & 0x6)], resultE, 4);
}
#else
if (M & 2) {
result8 = __riscv_vfmacc_vf_f64m1(result8, A1[0], resultE, 4);
resultA = __riscv_vfmacc_vf_f64m1(resultA, A1[1], resultE, 4);
}
if (M & 1) {
resultC = __riscv_vfmacc_vf_f64m1(resultC, A2[0], resultE, 4);
}
#endif
}
if (N & 3) {
#ifdef GEMM_NEW_PACKING
if (N & 1) {
B0 = B[0 + (N & 6)];
}
if (N & 2) {
B1 = B[0 + (N & 4)];
B2 = B[1 + (N & 4)];
}
#else
if (N & 1) {
B0 = B00[0];
B00 += 1;
}
if (N & 2) {
B1 = B01[0];
B2 = B01[1];
B01 += 2;
}
#endif
if (M & 4) {
result04 = __riscv_vle64_v_f64m1(A0, 4);
if (N & 1) {
result05 = __riscv_vfmacc_vf_f64m1(result05, B0, result04, 4);
}
if (N & 2) {
result06 = __riscv_vfmacc_vf_f64m1(result06, B1, result04, 4);
result07 = __riscv_vfmacc_vf_f64m1(result07, B2, result04, 4);
}
}
if (M & 2) {
#ifdef GEMM_NEW_PACKING
a0 = A0[0 + (M & 0x4)];
a1 = A0[1 + (M & 0x4)];
#else
a0 = A1[0];
a1 = A1[1];
#endif
if (N & 1) {
r0 += B0 * a0;
r1 += B0 * a1;
}
if (N & 2) {
r8 += B1 * a0;
r9 += B1 * a1;
rC += B2 * a0;
rD += B2 * a1;
}
}
if (M & 1) {
#ifdef GEMM_NEW_PACKING
a2 = A0[0 + (M & 0x6)];
#else
a2 = A2[0];
#endif
if (N & 1) {
r2 += B0 * a2;
}
if (N & 2) {
rA += B1 * a2;
rE += B2 * a2;
}
}
}
#ifdef GEMM_NEW_PACKING
A0 += M;
B += N;
#else
if (M & 4) {
A0 += 4;
}
if (M & 2) {
A1 += 2;
}
if (M & 1) {
A2 += 1;
}
if (N & 4) {
B += 4;
}
#endif
}
if (N & 4) {
FLOAT* C2 = C;
if (M & 4) {
vfloat64m1x4_t c14 = __riscv_vlsseg4e64_v_f64m1x4(C2, ldc * sizeof(FLOAT), 4);
c14 = __riscv_vset_v_f64m1_f64m1x4(c14, 0, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x4_f64m1(c14, 0), alpha, result0, 4));
c14 = __riscv_vset_v_f64m1_f64m1x4(c14, 1, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x4_f64m1(c14, 1), alpha, result2, 4));
c14 = __riscv_vset_v_f64m1_f64m1x4(c14, 2, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x4_f64m1(c14, 2), alpha, result4, 4));
c14 = __riscv_vset_v_f64m1_f64m1x4(c14, 3, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x4_f64m1(c14, 3), alpha, result6, 4));
__riscv_vssseg4e64_v_f64m1x4(C2, ldc * sizeof(FLOAT), c14, 4);
if (M & 3) {
C2 += 4;
}
}
if ((M & 3) == 1) {
vfloat64m1_t cC;
if (S) {
cC = __riscv_vle64_v_f64m1(C2, 4);
} else {
cC = __riscv_vlse64_v_f64m1(C2, ldc * sizeof(FLOAT), 4);
}
cC = __riscv_vfmacc_vf_f64m1(cC, alpha, resultC, 4);
if (S) {
__riscv_vse64_v_f64m1(C2, cC, 4);
} else {
__riscv_vsse64_v_f64m1(C2, ldc * sizeof(FLOAT), cC, 4);
}
} else if ((M & 3) == 2) {
vfloat64m1x2_t c12;
if (S) {
c12 = __riscv_vlseg2e64_v_f64m1x2(C2, 4);
} else {
c12 = __riscv_vlsseg2e64_v_f64m1x2(C2, ldc * sizeof(FLOAT), 4);
}
c12 = __riscv_vset_v_f64m1_f64m1x2(c12, 0, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x2_f64m1(c12, 0), alpha, result8, 4));
c12 = __riscv_vset_v_f64m1_f64m1x2(c12, 1, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x2_f64m1(c12, 1), alpha, resultA, 4));
if (S) {
__riscv_vsseg2e64_v_f64m1x2(C2, c12, 4);
} else {
__riscv_vssseg2e64_v_f64m1x2(C2, ldc * sizeof(FLOAT), c12, 4);
}
} else if ((M & 3) == 3) {
vfloat64m1x3_t c13;
if (S) {
c13 = __riscv_vlseg3e64_v_f64m1x3(C2, 4);
} else {
c13 = __riscv_vlsseg3e64_v_f64m1x3(C2, ldc * sizeof(FLOAT), 4);
}
c13 = __riscv_vset_v_f64m1_f64m1x3(c13, 0, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x3_f64m1(c13, 0), alpha, result8, 4));
c13 = __riscv_vset_v_f64m1_f64m1x3(c13, 1, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x3_f64m1(c13, 1), alpha, resultA, 4));
c13 = __riscv_vset_v_f64m1_f64m1x3(c13, 2, __riscv_vfmacc_vf_f64m1(__riscv_vget_v_f64m1x3_f64m1(c13, 2), alpha, resultC, 4));
if (S) {
__riscv_vsseg3e64_v_f64m1x3(C2, c13, 4);
} else {
__riscv_vssseg3e64_v_f64m1x3(C2, ldc * sizeof(FLOAT), c13, 4);
}
}
if (N & 3) {
C += (4 * ldc);
}
}
if (N & 3) {
FLOAT* C1, *C2;
if (N & 1) {
C1 = C + ((N & 2) * ldc);
}
if (N & 2) {
C2 = C + ldc;
}
if (M & 4) {
if (N & 2) {
result0 = __riscv_vle64_v_f64m1(C, 4);
result2 = __riscv_vle64_v_f64m1(C2, 4);
result0 = __riscv_vfmacc_vf_f64m1(result0, alpha, result06, 4);
result2 = __riscv_vfmacc_vf_f64m1(result2, alpha, result07, 4);
__riscv_vse64_v_f64m1(C, result0, 4);
__riscv_vse64_v_f64m1(C2, result2, 4);
}
if (N & 1) {
result4 = __riscv_vle64_v_f64m1(C1, 4);
result4 = __riscv_vfmacc_vf_f64m1(result4, alpha, result05, 4);
__riscv_vse64_v_f64m1(C1, result4, 4);
}
if (M & 3) {
if (N & 2) {
C += 4;
C2 += 4;
}
if (N & 1) {
C1 += 4;
}
}
}
if (M & 2) {
if (N & 2) {
C[0] += alpha * r8;
C[1] += alpha * r9;
C2[0] += alpha * rC;
C2[1] += alpha * rD;
}
if (N & 1) {
C1[0] += alpha * r0;
C1[1] += alpha * r1;
}
if (M & 1) {
if (N & 2) {
C += 2;
C2 += 2;
}
if (N & 1) {
C1 += 2;
}
}
}
if (M & 1) {
if (N & 2) {
C[0] += alpha * rA;
C2[0] += alpha * rE;
}
if (N & 1) {
C1[0] += alpha * r2;
}
}
}
}
return B;
}
#define GCC_COMPILER (defined(__GNUC__) && !defined(__clang__))
static FORCEINLINE FLOAT* M_TAIL(BLASLONG K, const BLASLONG M, const BLASLONG N, const bool S, FLOAT alpha, FLOAT* A0, FLOAT* B, FLOAT* C, BLASLONG ldc)
{
FLOAT *A1, *A2;
#ifndef GEMM_NEW_PACKING
if (M & 2) {
A1 = A0 + (K * (M & 0x4));
} else
#endif
{
#ifdef GCC_COMPILER
A1 = A0;
#endif
}
#ifndef GEMM_NEW_PACKING
if (M & 1) {
A2 = A0 + (K * (M & 0x6));
} else
#endif
{
#ifdef GCC_COMPILER
A2 = A0;
#endif
}
if (M & 4) {
if (M & 2) {
if (M & 1) {
return M_TAIL_ONE(K, 7, N, false, alpha, A0, A1, A2, B, C, ldc);
} else {
return M_TAIL_ONE(K, 6, N, false, alpha, A0, A1, A0, B, C, ldc);
}
} else {
if (M & 1) {
return M_TAIL_ONE(K, 5, N, false, alpha, A0, A0, A2, B, C, ldc);
} else {
return M_TAIL_ONE(K, 4, N, false, alpha, A0, A0, A0, B, C, ldc);
}
}
} else if (M & 2) {
if (M & 1) {
if (S) {
return M_TAIL_ONE(K, 3, N, true, alpha, A0, A1, A2, B, C, 3);
} else {
return M_TAIL_ONE(K, 3, N, false, alpha, A0, A1, A2, B, C, ldc);
}
} else {
if (S) {
return M_TAIL_ONE(K, 2, N, true, alpha, A0, A1, A0, B, C, 2);
} else {
return M_TAIL_ONE(K, 2, N, false, alpha, A0, A1, A0, B, C, ldc);
}
}
} else {
if (S) {
return M_TAIL_ONE(K, 1, N, true, alpha, A0, A0, A2, B, C, 1);
} else {
return M_TAIL_ONE(K, 1, N, false, alpha, A0, A0, A2, B, C, ldc);
}
}
}
static void FORCEINLINE N_TAIL_ONE(BLASLONG K, BLASLONG M, const BLASLONG N, FLOAT alpha, FLOAT** A, FLOAT* B, FLOAT** C, BLASLONG ldc)
{
#ifndef GEMM_NEW_PACKING
FLOAT* B03, *B04;
if (N & 2) {
B03 = B + ((N & 4) * K);
}
if (N & 1) {
B04 = B + ((N & 6) * K);
}
#endif
#ifdef GEMM_BOTTOM_CHUNK
BLASLONG K3;
if (N == 1) {
K3 = (K / 8);
K = (K & 7) + 1;
} else if (N == 2) {
K3 = (K / 4);
K = (K & 3) + 1;
} else if (N <= 4) {
K3 = (K / 2);
K = (K & 1) + 1;
}
#endif
do {
FLOAT B0, B1, B2, B3, B4, B5, B6;
#ifdef GEMM_NEW_PACKING
FLOAT *B00 = B;
#else
FLOAT *B00, *B01, *B02;
if (N & 4) {
B00 = B;
}
if (N & 2) {
B01 = B03;
}
if (N & 1) {
B02 = B04;
}
#endif
vfloat64m2_t result0, result2, result4, result6, result8, resultA, resultC;
vfloat64m2_t A0;
#ifdef GEMM_BOTTOM_CHUNK
vfloat64m2_t A2, A4, A6;
vfloat64m2_t resultE;
FLOAT B7;
if (N == 1) {
if (K3) {
vfloat64m8_t A01 = __riscv_vle64_v_f64m8(*A, 8 * 4);
*A += (8 * 4);
A0 = __riscv_vget_v_f64m8_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m8_f64m2(A01, 1);
A4 = __riscv_vget_v_f64m8_f64m2(A01, 2);
A6 = __riscv_vget_v_f64m8_f64m2(A01, 3);
#ifdef GEMM_NEW_PACKING
B0 = B00[0];
B1 = B00[1];
B2 = B00[2];
B3 = B00[3];
B4 = B00[4];
B5 = B00[5];
B6 = B00[6];
B7 = B00[7];
B00 += (8 * 1);
#else
B0 = B02[0];
B1 = B02[1];
B2 = B02[2];
B3 = B02[3];
B4 = B02[4];
B5 = B02[5];
B6 = B02[6];
B7 = B02[7];
B02 += (8 * 1);
#endif
resultC = __riscv_vfmul_vf_f64m2(A0, B0, 8);
result0 = __riscv_vfmul_vf_f64m2(A2, B1, 8);
result2 = __riscv_vfmul_vf_f64m2(A4, B2, 8);
result4 = __riscv_vfmul_vf_f64m2(A6, B3, 8);
A01 = __riscv_vle64_v_f64m8(*A, 8 * 4);
A0 = __riscv_vget_v_f64m8_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m8_f64m2(A01, 1);
A4 = __riscv_vget_v_f64m8_f64m2(A01, 2);
A6 = __riscv_vget_v_f64m8_f64m2(A01, 3);
*A += (8 * 4);
result6 = __riscv_vfmul_vf_f64m2(A0, B4, 8);
result8 = __riscv_vfmul_vf_f64m2(A2, B5, 8);
resultA = __riscv_vfmul_vf_f64m2(A4, B6, 8);
resultE = __riscv_vfmul_vf_f64m2(A6, B7, 8);
for (BLASLONG k = K3; --k; ) {
A01 = __riscv_vle64_v_f64m8(*A, 8 * 4);
*A += (8 * 4);
A0 = __riscv_vget_v_f64m8_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m8_f64m2(A01, 1);
A4 = __riscv_vget_v_f64m8_f64m2(A01, 2);
A6 = __riscv_vget_v_f64m8_f64m2(A01, 3);
#ifdef GEMM_NEW_PACKING
B0 = B00[0];
B1 = B00[1];
B2 = B00[2];
B3 = B00[3];
B4 = B00[4];
B5 = B00[5];
B6 = B00[6];
B7 = B00[7];
B00 += (8 * 1);
#else
B0 = B02[0];
B1 = B02[1];
B2 = B02[2];
B3 = B02[3];
B4 = B02[4];
B5 = B02[5];
B6 = B02[6];
B7 = B02[7];
B02 += (8 * 1);
#endif
resultC = __riscv_vfmacc_vf_f64m2(resultC, B0, A0, 8);
result0 = __riscv_vfmacc_vf_f64m2(result0, B1, A2, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, B2, A4, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, B3, A6, 8);
A01 = __riscv_vle64_v_f64m8(*A, 8 * 4);
A0 = __riscv_vget_v_f64m8_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m8_f64m2(A01, 1);
A4 = __riscv_vget_v_f64m8_f64m2(A01, 2);
A6 = __riscv_vget_v_f64m8_f64m2(A01, 3);
*A += (8 * 4);
result6 = __riscv_vfmacc_vf_f64m2(result6, B4, A0, 8);
result8 = __riscv_vfmacc_vf_f64m2(result8, B5, A2, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, B6, A4, 8);
resultE = __riscv_vfmacc_vf_f64m2(resultE, B7, A6, 8);
}
resultC = __riscv_vfadd_vv_f64m2(resultC, result6, 8);
result0 = __riscv_vfadd_vv_f64m2(result0, result8, 8);
result2 = __riscv_vfadd_vv_f64m2(result2, resultA, 8);
result4 = __riscv_vfadd_vv_f64m2(result4, resultE, 8);
resultC = __riscv_vfadd_vv_f64m2(resultC, result2, 8);
result0 = __riscv_vfadd_vv_f64m2(result0, result4, 8);
resultC = __riscv_vfadd_vv_f64m2(resultC, result0, 8);
} else {
resultC = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
}
} else if (N == 2) {
if (K3) {
vfloat64m8_t A01 = __riscv_vle64_v_f64m8(*A, 8 * 4);
A0 = __riscv_vget_v_f64m8_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m8_f64m2(A01, 1);
A4 = __riscv_vget_v_f64m8_f64m2(A01, 2);
A6 = __riscv_vget_v_f64m8_f64m2(A01, 3);
*A += (8 * 4);
#ifdef GEMM_NEW_PACKING
B0 = B00[0 + (2 * 0)];
B1 = B00[1 + (2 * 0)];
B2 = B00[0 + (2 * 1)];
B3 = B00[1 + (2 * 1)];
B4 = B00[0 + (2 * 2)];
B5 = B00[1 + (2 * 2)];
B6 = B00[0 + (2 * 3)];
B7 = B00[1 + (2 * 3)];
B00 += (2 * 4);
#else
B0 = B01[0 + (2 * 0)];
B1 = B01[1 + (2 * 0)];
B2 = B01[0 + (2 * 1)];
B3 = B01[1 + (2 * 1)];
B4 = B01[0 + (2 * 2)];
B5 = B01[1 + (2 * 2)];
B6 = B01[0 + (2 * 3)];
B7 = B01[1 + (2 * 3)];
B01 += (2 * 4);
#endif
result8 = __riscv_vfmul_vf_f64m2(A0, B0, 8);
resultA = __riscv_vfmul_vf_f64m2(A0, B1, 8);
result0 = __riscv_vfmul_vf_f64m2(A2, B2, 8);
result2 = __riscv_vfmul_vf_f64m2(A2, B3, 8);
result4 = __riscv_vfmul_vf_f64m2(A4, B4, 8);
result6 = __riscv_vfmul_vf_f64m2(A4, B5, 8);
resultC = __riscv_vfmul_vf_f64m2(A6, B6, 8);
resultE = __riscv_vfmul_vf_f64m2(A6, B7, 8);
for (BLASLONG k = K3; --k; ) {
A01 = __riscv_vle64_v_f64m8(*A, 8 * 4);
A0 = __riscv_vget_v_f64m8_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m8_f64m2(A01, 1);
A4 = __riscv_vget_v_f64m8_f64m2(A01, 2);
A6 = __riscv_vget_v_f64m8_f64m2(A01, 3);
*A += (8 * 4);
#ifdef GEMM_NEW_PACKING
B0 = B00[0 + (2 * 0)];
B1 = B00[1 + (2 * 0)];
B2 = B00[0 + (2 * 1)];
B3 = B00[1 + (2 * 1)];
B4 = B00[0 + (2 * 2)];
B5 = B00[1 + (2 * 2)];
B6 = B00[0 + (2 * 3)];
B7 = B00[1 + (2 * 3)];
B00 += (2 * 4);
#else
B0 = B01[0 + (2 * 0)];
B1 = B01[1 + (2 * 0)];
B2 = B01[0 + (2 * 1)];
B3 = B01[1 + (2 * 1)];
B4 = B01[0 + (2 * 2)];
B5 = B01[1 + (2 * 2)];
B6 = B01[0 + (2 * 3)];
B7 = B01[1 + (2 * 3)];
B01 += (2 * 4);
#endif
result8 = __riscv_vfmacc_vf_f64m2(result8, B0, A0, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, B1, A0, 8);
result0 = __riscv_vfmacc_vf_f64m2(result0, B2, A2, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, B3, A2, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, B4, A4, 8);
result6 = __riscv_vfmacc_vf_f64m2(result6, B5, A4, 8);
resultC = __riscv_vfmacc_vf_f64m2(resultC, B6, A6, 8);
resultE = __riscv_vfmacc_vf_f64m2(resultE, B7, A6, 8);
}
result8 = __riscv_vfadd_vv_f64m2(result8, result0, 8);
resultA = __riscv_vfadd_vv_f64m2(resultA, result2, 8);
result4 = __riscv_vfadd_vv_f64m2(result4, resultC, 8);
result6 = __riscv_vfadd_vv_f64m2(result6, resultE, 8);
result8 = __riscv_vfadd_vv_f64m2(result8, result4, 8);
resultA = __riscv_vfadd_vv_f64m2(resultA, result6, 8);
} else {
result8 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
resultA = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
}
} else if (N <= 4) {
if (K3) {
vfloat64m4_t A01 = __riscv_vle64_v_f64m4(*A, 4 * 4);
A0 = __riscv_vget_v_f64m4_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m4_f64m2(A01, 1);
*A += (4 * 4);
if (N == 4) {
B0 = B00[0];
B1 = B00[1];
B2 = B00[2];
B3 = B00[3];
B4 = B00[4];
B5 = B00[5];
B6 = B00[6];
B7 = B00[7];
#ifndef GEMM_NEW_PACKING
B00 += (4 * 2);
#endif
}
#ifdef GEMM_NEW_PACKING
if (N & 2) {
B0 = B00[0 + (N * 0)];
B1 = B00[1 + (N * 0)];
B4 = B00[0 + (N * 1)];
B5 = B00[1 + (N * 1)];
}
if (N & 1) {
B2 = B00[2 + (N * 0)];
B6 = B00[2 + (N * 1)];
}
B00 += (N * 2);
#else
if (N & 2) {
B0 = B01[0 + (2 * 0)];
B1 = B01[1 + (2 * 0)];
B4 = B01[0 + (2 * 1)];
B5 = B01[1 + (2 * 1)];
B01 += (2 * 2);
}
if (N & 1) {
B2 = B02[0 + (1 * 0)];
B6 = B02[0 + (1 * 1)];
B02 += (1 * 2);
}
#endif
if (N == 4) {
result0 = __riscv_vfmul_vf_f64m2(A0, B0, 8);
result2 = __riscv_vfmul_vf_f64m2(A0, B1, 8);
result4 = __riscv_vfmul_vf_f64m2(A0, B2, 8);
result6 = __riscv_vfmul_vf_f64m2(A0, B3, 8);
result8 = __riscv_vfmul_vf_f64m2(A2, B4, 8);
resultA = __riscv_vfmul_vf_f64m2(A2, B5, 8);
resultC = __riscv_vfmul_vf_f64m2(A2, B6, 8);
resultE = __riscv_vfmul_vf_f64m2(A2, B7, 8);
} else {
result8 = __riscv_vfmul_vf_f64m2(A0, B0, 8);
resultA = __riscv_vfmul_vf_f64m2(A0, B1, 8);
result0 = __riscv_vfmul_vf_f64m2(A2, B4, 8);
result2 = __riscv_vfmul_vf_f64m2(A2, B5, 8);
resultC = __riscv_vfmul_vf_f64m2(A0, B2, 8);
result4 = __riscv_vfmul_vf_f64m2(A2, B6, 8);
}
for (BLASLONG k = K3; --k; ) {
A01 = __riscv_vle64_v_f64m4(*A, 4 * 4);
A0 = __riscv_vget_v_f64m4_f64m2(A01, 0);
A2 = __riscv_vget_v_f64m4_f64m2(A01, 1);
*A += (4 * 4);
if (N == 4) {
B0 = B00[0];
B1 = B00[1];
B2 = B00[2];
B3 = B00[3];
B4 = B00[4];
B5 = B00[5];
B6 = B00[6];
B7 = B00[7];
#ifndef GEMM_NEW_PACKING
B00 += (4 * 2);
#endif
}
#ifdef GEMM_NEW_PACKING
if (N & 2) {
B0 = B00[0 + (N * 0)];
B1 = B00[1 + (N * 0)];
B4 = B00[0 + (N * 1)];
B5 = B00[1 + (N * 1)];
}
if (N & 1) {
B2 = B00[2 + (N * 0)];
B6 = B00[2 + (N * 1)];
}
B00 += (N * 2);
#else
if (N & 2) {
B0 = B01[0 + (2 * 0)];
B1 = B01[1 + (2 * 0)];
B4 = B01[0 + (2 * 1)];
B5 = B01[1 + (2 * 1)];
B01 += (2 * 2);
}
if (N & 1) {
B2 = B02[0 + (1 * 0)];
B6 = B02[0 + (1 * 1)];
B02 += (1 * 2);
}
#endif
if (N == 4) {
result0 = __riscv_vfmacc_vf_f64m2(result0, B0, A0, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, B1, A0, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, B2, A0, 8);
result6 = __riscv_vfmacc_vf_f64m2(result6, B3, A0, 8);
result8 = __riscv_vfmacc_vf_f64m2(result8, B4, A2, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, B5, A2, 8);
resultC = __riscv_vfmacc_vf_f64m2(resultC, B6, A2, 8);
resultE = __riscv_vfmacc_vf_f64m2(resultE, B7, A2, 8);
} else {
result8 = __riscv_vfmacc_vf_f64m2(result8, B0, A0, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, B1, A0, 8);
result0 = __riscv_vfmacc_vf_f64m2(result0, B4, A2, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, B5, A2, 8);
resultC = __riscv_vfmacc_vf_f64m2(resultC, B2, A0, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, B6, A2, 8);
}
}
if (N == 4) {
result0 = __riscv_vfadd_vv_f64m2(result0, result8, 8);
result2 = __riscv_vfadd_vv_f64m2(result2, resultA, 8);
result4 = __riscv_vfadd_vv_f64m2(result4, resultC, 8);
result6 = __riscv_vfadd_vv_f64m2(result6, resultE, 8);
} else {
result8 = __riscv_vfadd_vv_f64m2(result8, result0, 8);
resultA = __riscv_vfadd_vv_f64m2(resultA, result2, 8);
resultC = __riscv_vfadd_vv_f64m2(resultC, result4, 8);
}
} else {
if (N == 4) {
result0 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
result2 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
result4 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
result6 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
} else {
result8 = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
resultA = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
resultC = __riscv_vreinterpret_v_u64m2_f64m2(__riscv_vmv_v_x_u64m2(0, 8));
}
}
} else
#endif
{
if (N & 4) {
B0 = B00[0];
B1 = B00[1];
B2 = B00[2];
B3 = B00[3];
#ifndef GEMM_NEW_PACKING
B00 += 4;
#endif
}
#ifdef GEMM_NEW_PACKING
// Can write better code for GEMM_NEW_PACKING in which N > 4
if (N & 2) {
B4 = B00[0 + (N & 4)];
B5 = B00[1 + (N & 4)];
}
if (N & 1) {
B6 = B00[0 + (N & 6)];
}
B00 += N;
#else
if (N & 2) {
B4 = B01[0];
B5 = B01[1];
B01 += 2;
}
if (N & 1) {
B6 = B02[0];
B02 += 1;
}
#endif
A0 = __riscv_vle64_v_f64m2(*A, 4 * 2);
*A += 8;
if (N & 4) {
result0 = __riscv_vfmul_vf_f64m2(A0, B0, 8);
result2 = __riscv_vfmul_vf_f64m2(A0, B1, 8);
result4 = __riscv_vfmul_vf_f64m2(A0, B2, 8);
result6 = __riscv_vfmul_vf_f64m2(A0, B3, 8);
}
if (N & 2) {
result8 = __riscv_vfmul_vf_f64m2(A0, B4, 8);
resultA = __riscv_vfmul_vf_f64m2(A0, B5, 8);
}
if (N & 1) {
resultC = __riscv_vfmul_vf_f64m2(A0, B6, 8);
}
}
for (BLASLONG k = K; --k; ) {
if (N & 4) {
B0 = B00[0];
B1 = B00[1];
B2 = B00[2];
B3 = B00[3];
#ifndef GEMM_NEW_PACKING
B00 += 4;
#endif
}
#ifdef GEMM_NEW_PACKING
if (N & 2) {
B4 = B00[0 + (N & 4)];
B5 = B00[1 + (N & 4)];
}
if (N & 1) {
B6 = B00[0 + (N & 6)];
}
B00 += N;
#else
if (N & 2) {
B4 = B01[0];
B5 = B01[1];
B01 += 2;
}
if (N & 1) {
B6 = B02[0];
B02 += 1;
}
#endif
A0 = __riscv_vle64_v_f64m2(*A, 4 * 2);
*A += 8;
if (N & 4) {
result0 = __riscv_vfmacc_vf_f64m2(result0, B0, A0, 8);
result2 = __riscv_vfmacc_vf_f64m2(result2, B1, A0, 8);
result4 = __riscv_vfmacc_vf_f64m2(result4, B2, A0, 8);
result6 = __riscv_vfmacc_vf_f64m2(result6, B3, A0, 8);
}
if (N & 2) {
result8 = __riscv_vfmacc_vf_f64m2(result8, B4, A0, 8);
resultA = __riscv_vfmacc_vf_f64m2(resultA, B5, A0, 8);
}
if (N & 1) {
resultC = __riscv_vfmacc_vf_f64m2(resultC, B6, A0, 8);
}
}
FLOAT *C0 = *C;
vfloat64m2_t c0, c2, c4, c6, c8, cA, cC;
if (N & 4) {
c0 = __riscv_vle64_v_f64m2(C0, 8);
C0 += ldc;
c2 = __riscv_vle64_v_f64m2(C0, 8);
C0 += ldc;
c4 = __riscv_vle64_v_f64m2(C0, 8);
C0 += ldc;
c6 = __riscv_vle64_v_f64m2(C0, 8);
if (N & 3) {
C0 += ldc;
}
}
if (N & 2) {
c8 = __riscv_vle64_v_f64m2(C0, 8);
C0 += ldc;
cA = __riscv_vle64_v_f64m2(C0, 8);
if (N & 1) {
C0 += ldc;
}
}
if (N & 1) {
cC = __riscv_vle64_v_f64m2(C0, 8);
}
if (N & 4) {
c0 = __riscv_vfmacc_vf_f64m2(c0, alpha, result0, 8);
c2 = __riscv_vfmacc_vf_f64m2(c2, alpha, result2, 8);
c4 = __riscv_vfmacc_vf_f64m2(c4, alpha, result4, 8);
c6 = __riscv_vfmacc_vf_f64m2(c6, alpha, result6, 8);
}
if (N & 2) {
c8 = __riscv_vfmacc_vf_f64m2(c8, alpha, result8, 8);
cA = __riscv_vfmacc_vf_f64m2(cA, alpha, resultA, 8);
}
if (N & 1) {
cC = __riscv_vfmacc_vf_f64m2(cC, alpha, resultC, 8);
}
C0 = *C;
*C += 8;
if (N & 4) {
__riscv_vse64_v_f64m2(C0, c0, 8);
C0 += ldc;
__riscv_vse64_v_f64m2(C0, c2, 8);
C0 += ldc;
__riscv_vse64_v_f64m2(C0, c4, 8);
C0 += ldc;
__riscv_vse64_v_f64m2(C0, c6, 8);
if (N & 3) {
C0 += ldc;
}
}
if (N & 2) {
__riscv_vse64_v_f64m2(C0, c8, 8);
C0 += ldc;
__riscv_vse64_v_f64m2(C0, cA, 8);
if (N & 1) {
C0 += ldc;
}
}
if (N & 1) {
__riscv_vse64_v_f64m2(C0, cC, 8);
}
} while (--M);
}
static void FORCEINLINE N_TAIL(BLASLONG K, const BLASLONG M, const BLASLONG N, FLOAT alpha, FLOAT** A, FLOAT* B, FLOAT** C, BLASLONG ldc)
{
if (N & 4) {
if (N & 2) {
if (N & 1) {
N_TAIL_ONE(K, M, 7, alpha, A, B, C, ldc);
} else {
N_TAIL_ONE(K, M, 6, alpha, A, B, C, ldc);
}
} else {
if (N & 1) {
N_TAIL_ONE(K, M, 5, alpha, A, B, C, ldc);
} else {
N_TAIL_ONE(K, M, 4, alpha, A, B, C, ldc);
}
}
} else if (N & 2) {
if (N & 1) {
N_TAIL_ONE(K, M, 3, alpha, A, B, C, ldc);
} else {
N_TAIL_ONE(K, M, 2, alpha, A, B, C, ldc);
}
} else {
N_TAIL_ONE(K, M, 1, alpha, A, B, C, ldc);
}
}
static void NM_TAIL(BLASLONG K, BLASLONG M, const BLASLONG m_edge, const BLASLONG N, const BLASLONG S, FLOAT alpha, FLOAT* A, FLOAT* B, FLOAT* C, BLASLONG ldc)
{
if (M) {
N_TAIL(K, M, N, alpha, &A, B, &C, ldc);
}
if (m_edge) {
if (N & 4) {
if (N & 2) {
if (N & 1) {
M_TAIL(K, m_edge, 7, S, alpha, A, B, C, ldc);
} else {
M_TAIL(K, m_edge, 6, S, alpha, A, B, C, ldc);
}
} else {
if (N & 1) {
M_TAIL(K, m_edge, 5, S, alpha, A, B, C, ldc);
} else {
M_TAIL(K, m_edge, 4, S, alpha, A, B, C, ldc);
}
}
} else if (N & 2) {
if (N & 1) {
M_TAIL(K, m_edge, 3, S, alpha, A, B, C, ldc);
} else {
M_TAIL(K, m_edge, 2, S, alpha, A, B, C, ldc);
}
} else {
M_TAIL(K, m_edge, 1, S, alpha, A, B, C, ldc);
}
}
}
int CNAME(BLASLONG M, BLASLONG N, BLASLONG K, FLOAT alpha, FLOAT* A, FLOAT* B, FLOAT* C, BLASLONG ldc)
{
if (K <= 0) return 0;
const BLASLONG m_edge = M & 7;
const bool S = (ldc == m_edge);
// -- MAIN PASS
FLOAT *C01 = C;
FLOAT *A00 = A;
for (BLASLONG j = (N / 8); j--; ) {
FLOAT *B00 = B;
for (BLASLONG i = (M / 8); i--; ) {
B = B00;
FLOAT B0 = B[0];
FLOAT B1 = B[1];
FLOAT B2 = B[2];
FLOAT B3 = B[3];
FLOAT B4 = B[4];
FLOAT B5 = B[5];
FLOAT B6 = B[6];
FLOAT B7 = B[7];
B += 8;
vfloat64m2_t A00 = __riscv_vle64_v_f64m2( A, 8 );
A += 8;
vfloat64m2_t result01 = __riscv_vfmul_vf_f64m2( A00, B0, 8 );
vfloat64m2_t result23 = __riscv_vfmul_vf_f64m2( A00, B1, 8 );
vfloat64m2_t result45 = __riscv_vfmul_vf_f64m2( A00, B2, 8 );
vfloat64m2_t result67 = __riscv_vfmul_vf_f64m2( A00, B3, 8 );
vfloat64m2_t result89 = __riscv_vfmul_vf_f64m2( A00, B4, 8 );
vfloat64m2_t resultAB = __riscv_vfmul_vf_f64m2( A00, B5, 8 );
vfloat64m2_t resultCD = __riscv_vfmul_vf_f64m2( A00, B6, 8 );
vfloat64m2_t resultEF = __riscv_vfmul_vf_f64m2( A00, B7, 8 );
for (BLASLONG k = K; --k; ) {
B0 = B[0];
B1 = B[1];
B2 = B[2];
B3 = B[3];
B4 = B[4];
B5 = B[5];
B6 = B[6];
B7 = B[7];
B += 8;
A00 = __riscv_vle64_v_f64m2( A, 8 );
A += 8;
result01 = __riscv_vfmacc_vf_f64m2( result01, B0, A00, 8 );
result23 = __riscv_vfmacc_vf_f64m2( result23, B1, A00, 8 );
result45 = __riscv_vfmacc_vf_f64m2( result45, B2, A00, 8 );
result67 = __riscv_vfmacc_vf_f64m2( result67, B3, A00, 8 );
result89 = __riscv_vfmacc_vf_f64m2( result89, B4, A00, 8 );
resultAB = __riscv_vfmacc_vf_f64m2( resultAB, B5, A00, 8 );
resultCD = __riscv_vfmacc_vf_f64m2( resultCD, B6, A00, 8 );
resultEF = __riscv_vfmacc_vf_f64m2( resultEF, B7, A00, 8 );
}
FLOAT *C2 = C;
vfloat64m2_t c01 = __riscv_vle64_v_f64m2(C, 8); C += ldc;
vfloat64m2_t c23 = __riscv_vle64_v_f64m2(C, 8); C += ldc;
vfloat64m2_t c45 = __riscv_vle64_v_f64m2(C, 8); C += ldc;
vfloat64m2_t c67 = __riscv_vle64_v_f64m2(C, 8); C += ldc;
c01 = __riscv_vfmacc_vf_f64m2( c01, alpha, result01, 8 );
c23 = __riscv_vfmacc_vf_f64m2( c23, alpha, result23, 8 );
c45 = __riscv_vfmacc_vf_f64m2( c45, alpha, result45, 8 );
c67 = __riscv_vfmacc_vf_f64m2( c67, alpha, result67, 8 );
vfloat64m2_t c89 = __riscv_vle64_v_f64m2(C, 8); C += ldc;
vfloat64m2_t cAB = __riscv_vle64_v_f64m2(C, 8); C += ldc;
vfloat64m2_t cCD = __riscv_vle64_v_f64m2(C, 8); C += ldc;
vfloat64m2_t cEF = __riscv_vle64_v_f64m2(C, 8);
c89 = __riscv_vfmacc_vf_f64m2( c89, alpha, result89, 8 );
cAB = __riscv_vfmacc_vf_f64m2( cAB, alpha, resultAB, 8 );
cCD = __riscv_vfmacc_vf_f64m2( cCD, alpha, resultCD, 8 );
cEF = __riscv_vfmacc_vf_f64m2( cEF, alpha, resultEF, 8 );
C = C2;
__riscv_vse64_v_f64m2(C, c01, 8); C += ldc;
__riscv_vse64_v_f64m2(C, c23, 8); C += ldc;
__riscv_vse64_v_f64m2(C, c45, 8); C += ldc;
__riscv_vse64_v_f64m2(C, c67, 8); C += ldc;
__riscv_vse64_v_f64m2(C, c89, 8); C += ldc;
__riscv_vse64_v_f64m2(C, cAB, 8); C += ldc;
__riscv_vse64_v_f64m2(C, cCD, 8); C += ldc;
__riscv_vse64_v_f64m2(C, cEF, 8);
C = C2 + 8;
}
if (m_edge) {
B = M_TAIL(K, m_edge, 8, S, alpha, A, B00, C, ldc);
}
C01 += 8*ldc;
C = C01;
A = A00;
}
// -- tails for N<=7
if (N & 7) {
NM_TAIL(K, M / 8, m_edge, N, S, alpha, A, B, C, ldc);
}
return 0;
}