From ee9c019556d7c3133aca55fa02ef2d6e20893f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Thu, 2 Jul 2026 11:50:07 +0800 Subject: [PATCH] mlas: add missing LoongArch64 kernel headers to fix build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 吴小白 <296015668@qq.com> --- .../mlas/lib/loongarch64/FgemmKernelCommon.h | 100 ++++ .../lib/loongarch64/FgemmKernelLasxCommon.h | 546 ++++++++++++++++++ .../lib/loongarch64/FgemmKernelLsxCommon.h | 170 ++++++ .../mlas/lib/loongarch64/SgemmKernelCommon.h | 35 ++ 4 files changed, 851 insertions(+) create mode 100644 3rdparty/mlas/lib/loongarch64/FgemmKernelCommon.h create mode 100644 3rdparty/mlas/lib/loongarch64/FgemmKernelLasxCommon.h create mode 100644 3rdparty/mlas/lib/loongarch64/FgemmKernelLsxCommon.h create mode 100644 3rdparty/mlas/lib/loongarch64/SgemmKernelCommon.h diff --git a/3rdparty/mlas/lib/loongarch64/FgemmKernelCommon.h b/3rdparty/mlas/lib/loongarch64/FgemmKernelCommon.h new file mode 100644 index 0000000000..777a592590 --- /dev/null +++ b/3rdparty/mlas/lib/loongarch64/FgemmKernelCommon.h @@ -0,0 +1,100 @@ +/*++ + +Copyright (C) 2023 Loongson Technology Corporation Limited. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + FgemmKernelCommon.h + +Abstract: + + This module contains common kernel macros and structures for the floating + point matrix/matrix multiply operation (SGEMM and DGEMM). + +--*/ + +// +// Define the typed instruction template. +// + +#define FGEMM_TYPED_INSTRUCTION(Untyped, Typed) \ + .macro Untyped Operand:vararg; Typed \Operand\(); .endm; + +/*++ + +Macro Description: + + This macro generates code to execute the block compute macro multiple + times and advancing the matrix A and matrix B data pointers. + +Arguments: + + ComputeBlock - Supplies the macro to compute a single block. + + RowCount - Supplies the number of rows to process. + + AdvanceMatrixAPlusRows - Supplies a non-zero value if the data pointer + in rbx should also be advanced as part of the loop. + +Implicit Arguments: + + a0 - Supplies the address into the matrix A data. + + t7 - Supplies the address into the matrix A data plus 3 rows. + + a1 - Supplies the address into the matrix B data. + + a3 - Supplies the number of columns from matrix A and the number of rows + from matrix B to iterate over. + + vr4-vr15 - Supplies the block accumulators. + +--*/ + + .macro ComputeBlockLoop ComputeBlock, RowCount, AdvanceMatrixAPlusRows + + move $t8, $a3 # reload CountK + li.d $s0, 4 + blt $t8, $s0, .LProcessRemainingBlocks\@ + +.LComputeBlockBy4Loop\@: + \ComputeBlock\() \RowCount\(), 0, LFgemmElementSize*0, 64*4 + \ComputeBlock\() \RowCount\(), 2*32, LFgemmElementSize*1, 64*4 + addi.d $a1, $a1, 2*2*32 # advance matrix B by 128 bytes + \ComputeBlock\() \RowCount\(), 0, LFgemmElementSize*2, 64*4 + \ComputeBlock\() \RowCount\(), 2*32, LFgemmElementSize*3, 64*4 + addi.d $a1, $a1, 2*2*32 # advance matrix B by 128 bytes + addi.d $a0, $a0, 4*LFgemmElementSize # advance matrix A by 4 elements +.if \RowCount\() > 3 + addi.d $t7, $t7, 4*LFgemmElementSize # advance matrix A plus rows by 4 elements +.if \RowCount\() == 12 + addi.d $t3, $t3, 4*LFgemmElementSize + addi.d $t4,, $t4, 4*LFgemmElementSize +.endif +.endif + addi.d $t8, $t8, -4 + li.d $s0, 4 + bge $t8, $s0, .LComputeBlockBy4Loop\@ + +.LProcessRemainingBlocks\@: + beqz $t8, .LOutputBlock\@ + +.LComputeBlockBy1Loop\@: + \ComputeBlock\() \RowCount\(), 0, 0 + addi.d $a1, $a1, 2*32 # advance matrix B by 64 bytes + addi.d $a0, $a0, LFgemmElementSize # advance matrix A by 1 element +.if \RowCount\() > 3 + addi.d $t7, $t7, LFgemmElementSize # advance matrix A plus rows by 1 element +.if \RowCount\() == 12 + addi.d $t3, $t3, LFgemmElementSize + addi.d $t4, $t4, LFgemmElementSize +.endif +.endif + addi.d $t8, $t8, -1 + bnez $t8, .LComputeBlockBy1Loop\@ + +.LOutputBlock\@: + + .endm diff --git a/3rdparty/mlas/lib/loongarch64/FgemmKernelLasxCommon.h b/3rdparty/mlas/lib/loongarch64/FgemmKernelLasxCommon.h new file mode 100644 index 0000000000..b96db84861 --- /dev/null +++ b/3rdparty/mlas/lib/loongarch64/FgemmKernelLasxCommon.h @@ -0,0 +1,546 @@ + +/*++ + +Copyright (C) 2023 Loongson Technology Corporation Limited. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + FgemmKernelLasxCommon.h + +Abstract: + + This module implements the kernels for the floating point matrix/matrix + multiply operation (SGEMM and DGEMM). + + This implementation uses LASX instructions. + +--*/ + +/*++ + +Macro Description: + + This macro multiplies and accumulates for 2 YMMWORDs by N rows of the output + matrix. + +Arguments: + + RowCount - Supplies the number of rows to process. + + VectorOffset - Supplies the byte offset from matrix B to fetch elements. + + BroadcastOffset - Supplies the byte offset from matrix A to fetch elements. + + PrefetchOffset - Optionally supplies the byte offset from matrix B to + prefetch elements. + +Implicit Arguments: + + a0 - Supplies the address into the matrix A data. + + t7 - Supplies the address into the matrix A data plus 2 rows. + + a1 - Supplies the address into the matrix B data. + + t0 - Supplies the length in bytes of a row from matrix A. + + xr8-xr15 - Supplies the block accumulators. + +--*/ + + .macro ComputeBlockLasxBy16 RowCount, VectorOffset, BroadcastOffset, PrefetchOffset + +.if \RowCount\() == 1 + xvldrepl.w $xr3, $a0, \BroadcastOffset\() + xvld $xr4, $a1, \VectorOffset\() + xvfmadd $xr8, $xr4, $xr3, $xr8 + xvld $xr5, $a1, \VectorOffset\()+32 + xvfmadd $xr9, $xr5, $xr3, $xr9 +.else + xvld $xr0, $a1, \VectorOffset\() + xvld $xr1, $a1, \VectorOffset\()+32 + EmitIfCountGE \RowCount\(), 1, "xvldrepl $xr3,$a0, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 1, "xvfmadd $xr8, $xr3, $xr0, $xr8" + EmitIfCountGE \RowCount\(), 1, "xvfmadd $xr9, $xr3, $xr1, $xr9" + EmitIfCountGE \RowCount\(), 2, "add.d $s0,$a0, $t0" + EmitIfCountGE \RowCount\(), 2, "xvldrepl $xr3,$s0, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 2, "xvfmadd $xr10, $xr3, $xr0, $xr10" + EmitIfCountGE \RowCount\(), 2, "xvfmadd $xr11, $xr3, $xr1, $xr11" + + EmitIfCountGE \RowCount\(), 3, "xvldrepl $xr3,$t7, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 3, "xvfmadd $xr12, $xr3, $xr0, $xr12" + EmitIfCountGE \RowCount\(), 3, "xvfmadd $xr13, $xr3, $xr1, $xr13" + EmitIfCountGE \RowCount\(), 4, "add.d $s0,$t7, $t0" + EmitIfCountGE \RowCount\(), 4, "xvldrepl $xr3,$s0, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 4, "xvfmadd $xr14, $xr3, $xr0, $xr14" + EmitIfCountGE \RowCount\(), 4, "xvfmadd $xr15, $xr3, $xr1, $xr15" +.endif + + .endm + +/*++ + +Macro Description: + + This macro multiplies and accumulates for 1 YMMWORD by N rows of the output + matrix. + +Arguments: + + RowCount - Supplies the number of rows to process. + + VectorOffset - Supplies the byte offset from matrix B to fetch elements. + + BroadcastOffset - Supplies the byte offset from matrix A to fetch elements. + + PrefetchOffset - Optionally supplies the byte offset from matrix B to + prefetch elements. + +Implicit Arguments: + + a0 - Supplies the address into the matrix A data. + + t7 - Supplies the address into the matrix A data plus 2 rows. + + a1 - Supplies the address into the matrix B data. + + t0 - Supplies the length in bytes of a row from matrix A. + + xr8-xr15 - Supplies the block accumulators. + +--*/ + + .macro ComputeBlockLasxBy8 RowCount, VectorOffset, BroadcastOffset, PrefetchOffset + +.if \RowCount\() == 1 + xvldrepl.w $xr3, $a0, \BroadcastOffset\() + xvld $xr5, $a1, \VectorOffset\() + xvfmadd.s $xr9, $xr5, $xr3, $xr9 +.else + xvld $xr0, $a1, \VectorOffset\() + EmitIfCountGE \RowCount\(), 1, "xvldrepl $xr3, $a0, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 1, "xvfmadd $xr9, $xr3, $xr0, $xr9" + + EmitIfCountGE \RowCount\(), 2, "add.d $s0, $a0, $t0" + EmitIfCountGE \RowCount\(), 2, "xvldrepl $xr3, $s0, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 2, "xvfmadd $xr11, $xr3, $xr0, $xr11" + EmitIfCountGE \RowCount\(), 3, "xvldrepl $xr3, $t7, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 3, "xvfmadd $xr13, $xr3, $xr0, $xr13" + EmitIfCountGE \RowCount\(), 4, "add.d $s0, $t7, $t0" + EmitIfCountGE \RowCount\(), 4, "xvldrepl $xr3, $s0, \BroadcastOffset\()" + EmitIfCountGE \RowCount\(), 4, "xvfmadd $xr15, $xr3, $xr0, $xr15" +.endif + + .endm + +/*++ + +Macro Description: + + This macro generates code to execute the block compute macro multiple + times and advancing the matrix A and matrix B data pointers. + +Arguments: + + ComputeBlock - Supplies the macro to compute a single block. + + RowCount - Supplies the number of rows to process. + +Implicit Arguments: + + a0 - Supplies the address into the matrix A data. + + a1 - Supplies the address into the matrix B data. + + a3 - Supplies the number of columns from matrix A and the number of rows + from matrix B to iterate over. + + t0 - Supplies the length in bytes of a row from matrix A. + + vr4-vr15 - Supplies the block accumulators. + +--*/ + + .macro ComputeBlockLasxLoop ComputeBlock, RowCount + +.if \RowCount\() > 2 + # compute matrix A plus 2 rows + slli.d $s0, $t0, 1 + add.d $t7, $a0, $s0 +.endif + ComputeBlockLoop \ComputeBlock\(), \RowCount\(), \RowCount\() > 2 +.if \RowCount\() > 2 + # compute matrix C plus 2 rows + slli.d $s0, $t6, 1 + add.d $t7, $a2, $s0 +.endif + + .endm + + .macro store_n src, num, dst + move $s2, \num\() + beqz $s2, .Lstore_exit\@ + xvstelm.w \src\(), \dst\(), 0, 0 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + + xvstelm.w \src\(), \dst\(), 4, 1 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + + xvstelm.w \src\(), \dst\(), 8, 2 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + + xvstelm.w \src\(), \dst\(), 12, 3 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + + xvstelm.w \src\(), \dst\(), 16, 4 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + + xvstelm.w \src\(), \dst\(), 20, 5 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + + xvstelm.w \src\(), \dst\(), 24, 6 + addi.d $s2, $s2, -1 + beqz $s2, .Lstore_exit\@ + +.Lstore_exit\@: + .endm +/*++ + +Macro Description: + + This macro generates code to compute matrix multiplication for a fixed set + of rows. + +Arguments: + + RowCount - Supplies the number of rows to process. + + Fallthrough - Supplies a non-blank value if the macro may fall through to + the ExitKernel label. + +Implicit Arguments: + + a0 - Supplies the address of matrix A. + + a1 - Supplies the address of matrix B. + + t1 - Supplies the address of matrix A. + + a5 - Supplies the number of columns from matrix B and matrix C to iterate + over. + + a2 - Supplies the address of matrix C. + + a3 - Supplies the number of columns from matrix A and the number of rows + from matrix B to iterate over. + + t0 - Supplies the length in bytes of a row from matrix A. + + t6 - Supplies the length in bytes of a row from matrix C. + + t5 - Stores the ZeroMode argument from the stack frame. + +--*/ + + .macro ProcessCountM RowCount, Fallthrough + + ori $s1, $r0, LFgemmYmmElementCount + bgeu $s1, $a5, .LProcessRemainingCountN\@ + +.LProcessNextColumnLoop2xN\@: + EmitIfCountGE \RowCount\(), 1, "xvxor.v $xr8, $xr8, $xr8" + EmitIfCountGE \RowCount\(), 1, "xvxor.v $xr9, $xr9, $xr9" + EmitIfCountGE \RowCount\(), 2, "xvxor.v $xr10, $xr10, $xr10" + EmitIfCountGE \RowCount\(), 2, "xvxor.v $xr11, $xr11, $xr11" + EmitIfCountGE \RowCount\(), 3, "xvxor.v $xr12, $xr12, $xr12" + EmitIfCountGE \RowCount\(), 3, "xvxor.v $xr13, $xr13, $xr13" + EmitIfCountGE \RowCount\(), 4, "xvxor.v $xr14, $xr14, $xr14" + EmitIfCountGE \RowCount\(), 4, "xvxor.v $xr15, $xr15, $xr15" + + ComputeBlockLasxLoop ComputeBlockLasxBy16, \RowCount\() + EmitIfCountGE \RowCount\(), 1, "xvfmul $xr8, $xr8, $xr2" + EmitIfCountGE \RowCount\(), 1, "xvfmul $xr9, $xr9, $xr2" + EmitIfCountGE \RowCount\(), 2, "xvfmul $xr10, $xr10, $xr2" + EmitIfCountGE \RowCount\(), 2, "xvfmul $xr11, $xr11, $xr2" + EmitIfCountGE \RowCount\(), 3, "xvfmul $xr12, $xr12, $xr2" + EmitIfCountGE \RowCount\(), 3, "xvfmul $xr13, $xr13, $xr2" + EmitIfCountGE \RowCount\(), 4, "xvfmul $xr14, $xr14, $xr2" + EmitIfCountGE \RowCount\(), 4, "xvfmul $xr15, $xr15, $xr2" + + sub.d $a5, $a5, $s1 + sub.d $a5, $a5, $s1 + blt $a5, $zero, .LOutputMasked2xNBlock\@ + andi $s0, $t5, 0xff # ZeroMode? + bnez $s0, .LStore2xNBlock\@ + EmitIfCountGE \RowCount\(), 1, "xvld $xr16, $a2, 0" + EmitIfCountGE \RowCount\(), 1, "xvfadd $xr8, $xr8, $xr16" + EmitIfCountGE \RowCount\(), 1, "xvld $xr16, $a2, 0x20" + EmitIfCountGE \RowCount\(), 1, "xvfadd $xr9, $xr9, $xr16" + EmitIfCountGE \RowCount\(), 2, "xvldx $xr16, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "xvfadd $xr10, $xr10, $xr16" + EmitIfCountGE \RowCount\(), 2, "add.d $s0, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "xvld $xr16, $s0, 0x20" + EmitIfCountGE \RowCount\(), 2, "xvfadd $xr11, $xr11, $xr16" + EmitIfCountGE \RowCount\(), 3, "xvld $xr16, $t7, 0" + EmitIfCountGE \RowCount\(), 3, "xvfadd $xr12, $xr12, $xr16" + EmitIfCountGE \RowCount\(), 3, "xvld $xr16, $t7, 0x20" + EmitIfCountGE \RowCount\(), 3, "xvfadd $xr13, $xr13, $xr16" + EmitIfCountGE \RowCount\(), 4, "xvldx $xr16, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "xvfadd $xr14, $xr14, $xr16" + EmitIfCountGE \RowCount\(), 4, "add.d $s0, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "xvld $xr16, $s0, 0x20" + EmitIfCountGE \RowCount\(), 4, "xvfadd $xr15, $xr15, $xr16" + +.LStore2xNBlock\@: + EmitIfCountGE \RowCount\(), 1, "xvst $xr8, $a2, 0" + EmitIfCountGE \RowCount\(), 1, "xvst $xr9, $a2, 0x20" + EmitIfCountGE \RowCount\(), 2, "xvstx $xr10, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "add.d $s0, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "xvst $xr11, $s0, 0x20" + EmitIfCountGE \RowCount\(), 3, "xvst $xr12, $t7, 0" + EmitIfCountGE \RowCount\(), 3, "xvst $xr13, $t7, 0x20" + EmitIfCountGE \RowCount\(), 4, "xvstx $xr14, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "add.d $s0, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "xvst $xr15, $s0, 0x20" + + addi.d $a2, $a2, 0x40 # advance matrix C by 2 XRWORDs + move $a0, $t1 # reload matrix A + bltu $s1, $a5, .LProcessNextColumnLoop2xN\@ + beqz $a5, .LExitKernel + +.LProcessRemainingCountN\@: + EmitIfCountGE \RowCount\(), 1, "xvxor.v $xr9, $xr9, $xr9" + EmitIfCountGE \RowCount\(), 2, "xvxor.v $xr11, $xr11, $xr11" + EmitIfCountGE \RowCount\(), 3, "xvxor.v $xr13, $xr13, $xr13" + EmitIfCountGE \RowCount\(), 4, "xvxor.v $xr15, $xr15, $xr15" + + + ComputeBlockLasxLoop ComputeBlockLasxBy8, \RowCount\() + EmitIfCountGE \RowCount\(), 1, "xvfmul $xr9, $xr9, $xr2" + EmitIfCountGE \RowCount\(), 2, "xvfmul $xr11, $xr11, $xr2" + EmitIfCountGE \RowCount\(), 3, "xvfmul $xr13, $xr13, $xr2" + EmitIfCountGE \RowCount\(), 4, "xvfmul $xr15, $xr15, $xr2" + bltu $a5, $s1, .LOutputMasked1xNBlock\@ + andi $s0, $t5, 0xff # ZeroMode? + bnez $s0, .LStore1xNBlock\@ + EmitIfCountGE \RowCount\(), 1, "xvld $xr16, $a2, 0" + EmitIfCountGE \RowCount\(), 1, "xvfadd $xr9, $xr9, $xr16" + EmitIfCountGE \RowCount\(), 2, "xvldx $xr16, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "xvfadd $xr11, $xr11, $xr16" + EmitIfCountGE \RowCount\(), 3, "xvld $xr16, $t7, 0" + EmitIfCountGE \RowCount\(), 3, "xvfadd $xr13, $xr13, $xr16" + EmitIfCountGE \RowCount\(), 4, "xvldx $xr16, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "xvfadd $xr15, $xr15, $xr16" + +.LStore1xNBlock\@: + EmitIfCountGE \RowCount\(), 1, "xvst $xr9, $a2, 0" + EmitIfCountGE \RowCount\(), 2, "xvstx $xr11, $a2, $t6" + EmitIfCountGE \RowCount\(), 3, "xvst $xr13, $t7, 0" + EmitIfCountGE \RowCount\(), 4, "xvstx $xr15, $t7, $t6" + b .LExitKernel + +.LOutputMasked2xNBlock\@: + andi $s0, $t5, 0xff # ZeroMode? + bnez $s0, .LStoreMasked2xNBlock\@ + EmitIfCountGE \RowCount\(), 1, "xvld $xr16, $a2, 0" + EmitIfCountGE \RowCount\(), 1, "xvfadd $xr8, $xr8, $xr16" + EmitIfCountGE \RowCount\(), 2, "xvldx $xr16, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "xvfadd $xr10, $xr10, $xr16" + EmitIfCountGE \RowCount\(), 3, "xvld $xr16, $t7, 0" + EmitIfCountGE \RowCount\(), 3, "xvfadd $xr12, $xr12, $xr16" + EmitIfCountGE \RowCount\(), 4, "xvldx $xr16, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "xvfadd $xr14, $xr14, $xr16" + +.LStoreMasked2xNBlock\@: + EmitIfCountGE \RowCount\(), 1, "xvst $xr8, $a2, 0" + EmitIfCountGE \RowCount\(), 2, "xvstx $xr10, $a2, $t6" + EmitIfCountGE \RowCount\(), 3, "xvst $xr12, $t7, 0" + EmitIfCountGE \RowCount\(), 4, "xvstx $xr14, $t7, $t6" + addi.d $a2, $a2, 0x20 # advance matrix C by YMMWORD +.if \RowCount\() > 2 + addi.d $t7, $t7, 0x20 # advance matrix C plus 2 rows by YMMWORD + +.endif + addi.d $a5, $a5, LFgemmYmmElementCount # correct for over-subtract above + + +.LOutputMasked1xNBlock\@: + +.if \RowCount\() > 2 + slli.d $s0, $t0, 1 + add.d $t7, $a0, $s0 +.endif + +.if \RowCount\() == 1 +.else +.endif + +.if \RowCount\() > 2 + slli.d $s0, $t6, 1 + add.d $t7, $a2, $s0 +.endif + + sub.d $a5, $zero, $a5 + la.global $a0, MlasMaskMoveTableLasx + ori $s0, $r0, LFgemmElementSize + mul.d $s0, $a5, $s0 + addi.d $s0, $s0, 8*4 + xvldx $xr0, $a0, $s0 + andi $s0, $t5, 0xff + + sub.d $a5, $zero, $a5 + + bnez $s0, .LStoreMasked1xNBlock\@ + EmitIfCountGE \RowCount\(), 1, "xvld $xr16, $a2, 0" + EmitIfCountGE \RowCount\(), 1, "xvand.v $xr8, $xr16, $xr0" + EmitIfCountGE \RowCount\(), 2, "xvldx $xr16, $a2, $t6" + EmitIfCountGE \RowCount\(), 2, "xvand.v $xr10, $xr16, $xr0" + EmitIfCountGE \RowCount\(), 3, "xvld $xr16, $t7, 0" + EmitIfCountGE \RowCount\(), 3, "xvand.v $xr12, $xr16, $xr0" + EmitIfCountGE \RowCount\(), 4, "xvldx $xr16, $t7, $t6" + EmitIfCountGE \RowCount\(), 4, "xvand.v $xr14, $xr16, $xr0" + + EmitIfCountGE \RowCount\(), 1, "xvfadd $xr9, $xr9, $xr8" + EmitIfCountGE \RowCount\(), 2, "xvfadd $xr11, $xr11, $xr10" + EmitIfCountGE \RowCount\(), 3, "xvfadd $xr13, $xr13, $xr12" + EmitIfCountGE \RowCount\(), 4, "xvfadd $xr15, $xr15, $xr14" +.LStoreMasked1xNBlock\@: + EmitIfCountGE \RowCount\(), 1, "store_n $xr9, $a5, $a2" + + add.d $s3, $a2, $t6 + EmitIfCountGE \RowCount\(), 2, "store_n $xr11, $a5, $s3" + + EmitIfCountGE \RowCount\(), 3, "store_n $xr13, $a5, $t7" + + add.d $s3, $t7, $t6 + EmitIfCountGE \RowCount\(), 4, "store_n $xr15, $a5, $s3" + sub.d $a5, $zero, $a5 +.ifb \Fallthrough\() + b .LExitKernel +.endif + + .endm + +/*++ + +Macro Description: + + This macro generates the inner kernel to compute matrix multiplication. + +Arguments: + + FunctionName - Supplies the name for the generated function. + +--*/ + + .macro FgemmKernelLasxFunction FunctionName + +/*++ + +Routine Description: + + This routine is an inner kernel to compute matrix multiplication for a + set of rows. + +Arguments: + + A a0 - Supplies the address of matrix A. + + B a1 - Supplies the address of matrix B. The matrix data has been packed + using MlasSgemmCopyPackB or MlasSgemmTransposePackB. + + C a2 - Supplies the address of matrix C. + + CountK a3 - Supplies the number of columns from matrix A and the number + of rows from matrix B to iterate over. + + CountM a4 - Supplies the maximum number of rows that can be processed for + matrix A and matrix C. The actual number of rows handled for this + invocation depends on the kernel implementation. + + CountN a5 - Supplies the number of columns from matrix B and matrix C to + iterate over. + + lda a6 - Supplies the first dimension of matrix A. + + ldc a7 - Supplies the first dimension of matrix C. + + Alpha f0 - Supplies the scalar alpha multiplier (see GEMM definition). + + ZeroMode (sp + 0)- Supplies true if the output matrix must be zero initialized, + else false if the output matrix is accumulated into. + +Return Value: + + Returns the number of rows handled. + +--*/ + + FUNCTION_ENTRY \FunctionName\() + + addi.d $sp, $sp, -64 + st.d $ra, $sp, 56 + st.d $s0, $sp, 0*8 + st.d $s1, $sp, 1*8 + fst.s $f0, $sp, 2*8 + fst.d $f16, $sp,3*8 + st.d $s2, $sp, 4*8 + st.d $s3, $sp, 5*8 + + move $t1, $a0 + slli.d $t0, $a6, 2 # convert lda to bytes + slli.d $t6, $a7, 2 # convert ldc to bytes + ld.d $t5, $sp, 64 # get zeromode + fst.s $f0, $sp, 2*8 + xvldrepl.w $xr2, $sp, 0x10 + +// +// Process 4 rows of the matrices. +// + + ori $s0, $zero, 4 + bltu $a4, $s0, .LProcessCountMLessThan4 + li.d $a4, 4 # return 4 rows handled + ProcessCountM 4, Fallthrough + +// +// Restore non-volatile registers and return. +// + +.LExitKernel: + bstrpick.d $a0, $a4, 31, 0 + ld.d $s0, $sp, 0 + ld.d $s1, $sp, 8 + fld.d $f16, $sp,3*8 + ld.d $s2, $sp, 4*8 + ld.d $s3, $sp, 5*8 + ld.d $ra, $sp, 7*8 + addi.d $sp, $sp, 64 + jr $ra + +// +// Process 2 rows of the matrices. +// + +.LProcessCountMLessThan4: + ori $s0, $r0, 2 + bltu $a4, $s0, .LProcessCountMLessThan2 + li.d $a4, 2 # return 2 rows handled + ProcessCountM 2 + +// +// Process 1 row of the matrices. +// + +.LProcessCountMLessThan2: + ProcessCountM 1 + + .endm diff --git a/3rdparty/mlas/lib/loongarch64/FgemmKernelLsxCommon.h b/3rdparty/mlas/lib/loongarch64/FgemmKernelLsxCommon.h new file mode 100644 index 0000000000..0333af792b --- /dev/null +++ b/3rdparty/mlas/lib/loongarch64/FgemmKernelLsxCommon.h @@ -0,0 +1,170 @@ +/*++ + +Copyright (C) 2023 Loongson Technology Corporation Limited. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + FgemmKernelLsxCommon.h + +Abstract: + + This module implements the kernels for the floating point matrix/matrix + multiply operation (SGEMM and DGEMM). + + This implementation uses Lsx instructions. + +--*/ + +#include "FgemmKernelCommon.h" +/*++ + +Macro Description: + + This stores the block accumulators to the output matrix with an optional + accumulation of the existing contents of the output matrix. + +Arguments: + + RowCount - Supplies the number of rows to process. + + VectorCount - Supplies the number of vector columns to process. + +Implicit Arguments: + + t5 - Supplies the length in bytes of a row from matrix C. + + a2 - Supplies the address of matrix C. + + s3 - Stores the ZeroMode argument from the stack frame. + + vr8-vr15 - Supplies the block accumulators. + +--*/ + + .macro AccumulateAndStoreBlock RowCount, VectorCount + + and $s0, $t5,$t5 # ZeroMode? + bnez $s0 , .LSkipAccumulateOutput\@ + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 1, "vld $vr0, $a2, 0" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 2, "vld $vr1, $a2, 16" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 3, "vld $vr2, $a2, 32" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 4, "vld $vr3, $a2, 48" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 1, "vldx $vr4, $a2, $t6" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 2, "addi.d $s0, $t6, 16" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 2, "vldx $vr5, $a2, $s0" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 3, "addi.d $s0, $t6, 32" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 3, "vldx $vr6, $a2, $s0" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 4, "addi.d $s0, $t6, 48" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 4, "vldx $vr7, $a2, $s0" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 1, "vfadd $vr8, $vr8, $vr0" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 2, "vfadd $vr9, $vr9, $vr1" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 3, "vfadd $vr10,$vr10,$vr2" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 4, "vfadd $vr11,$vr11,$vr3" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 1, "vfadd $vr12,$vr12,$vr4" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 2, "vfadd $vr13,$vr13,$vr5" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 3, "vfadd $vr14,$vr14,$vr6" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 4, "vfadd $vr15,$vr15,$vr7" + +.LSkipAccumulateOutput\@: + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 1, "vst $vr8, $a2, 0" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 2, "vst $vr9, $a2, 16" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 3, "vst $vr10, $a2, 32" + EmitIfCount2GE \RowCount\(), 1, \VectorCount\(), 4, "vst $vr11, $a2, 48" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 1, "vstx $vr12, $a2, $t6" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 2, "addi.d $s0, $t6, 16" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 2, "vstx $vr13, $a2, $s0" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 3, "addi.d $s0, $t6, 32" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 3, "vstx $vr14, $a2, $s0" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 4, "addi.d $s0, $t6, 48" + EmitIfCount2GE \RowCount\(), 2, \VectorCount\(), 4, "vstx $vr15, $a2, $s0" + + .endm +/*++ + +Macro Description: + + This macro generates the inner kernel to compute matrix multiplication. + +Arguments: + + FunctionName - Supplies the name for the generated function. + +--*/ + + .macro FgemmKernelLsxFunction FunctionName + +/*++ + +Routine Description: + + This routine is an inner kernel to compute matrix multiplication for a + set of rows. + +Arguments: + + A (a0) - Supplies the address of matrix A. + + B (a1) - Supplies the address of matrix B. The matrix data has been packed + using MlasSgemmCopyPackB or MlasSgemmTransposePackB. + + C (a2) - Supplies the address of matrix C. + + CountK (a3) - Supplies the number of columns from matrix A and the number + of rows from matrix B to iterate over. + + CountM (a4) - Supplies the maximum number of rows that can be processed for + matrix A and matrix C. The actual number of rows handled for this + invocation depends on the kernel implementation. + + CountN (a5) - Supplies the number of columns from matrix B and matrix C to + iterate over. + + lda (a6) Supplies the first dimension of matrix A. + + ldc (a7) Supplies the first dimension of matrix C. + + Alpha (f0) - Supplies the scalar alpha multiplier (see GEMM definition). + + ZeroMode (sp 0) - Supplies true if the output matrix must be zero initialized, + else false if the output matrix is accumulated into. + +Return Value: + + Returns the number of rows handled. + +--*/ + +FUNCTION_ENTRY \FunctionName\() + addi.d $sp, $sp, -64 + st.d $t5, $sp, 0 + st.d $s0, $sp, 1*8 + st.d $s1, $sp, 2*8 + st.d $s2, $sp, 3*8 + st.d $s3, $sp, 4*8 + move $t1, $a0 + slli.d $t0, $a6, 2 //convert lda to bytes + slli.d $t6, $a7, 2 //convert ldc to bytes + ld.d $t5, $sp, 64 + fmov.s $f24, $f0 //f0 destroyed by lsx + + li.d $s0, 2 + blt $a4, $s0, .LProcessCountM1 + + li.d $a4, 2 + ProcessCountM 2, Fallthrough + +.LExitKernel: + ld.d $t5, $sp, 0 + ld.d $s0, $sp, 1*8 + ld.d $s1, $sp, 2*8 + ld.d $s2, $sp, 3*8 + ld.d $s3, $sp, 4*8 + addi.d $sp, $sp, 64 + move $a0, $a4 + jr $ra + +.LProcessCountM1: + ProcessCountM 1 + .endm diff --git a/3rdparty/mlas/lib/loongarch64/SgemmKernelCommon.h b/3rdparty/mlas/lib/loongarch64/SgemmKernelCommon.h new file mode 100644 index 0000000000..93b109c90a --- /dev/null +++ b/3rdparty/mlas/lib/loongarch64/SgemmKernelCommon.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (C) 2023 Loongson Technology Corporation Limited. All rights reserved. + +Licensed under the MIT License. + +Module Name: + + SgemmKernelCommon.h + +Abstract: + + This module contains common kernel macros and structures for the single + precision matrix/matrix multiply operation (SGEMM). + +--*/ + +// +// Define the single precision parameters. +// + +#define LFgemmElementShift 2 +#define LFgemmElementSize (1 << LFgemmElementShift) +#define LFgemmYmmElementCount (32/LFgemmElementSize) + +#include "FgemmKernelCommon.h" + +// +// Define the typed instructions for single precision. +// + +FGEMM_TYPED_INSTRUCTION(xvfadd, xvfadd.s) +FGEMM_TYPED_INSTRUCTION(xvfmadd, xvfmadd.s) +FGEMM_TYPED_INSTRUCTION(xvldrepl, xvldrepl.w) +FGEMM_TYPED_INSTRUCTION(xvfmul, xvfmul.s)