1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00
Files
Abhishek Gola bdf348c13a Merge pull request #28934 from abhishek-gola:mlas_gemm
Added MLAS third party module and integrated into GeMM path #28934

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
2026-05-22 20:22:15 +03:00

274 lines
9.0 KiB
ArmAsm

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
Module Name:
SgemmKernelSse2.s
Abstract:
This module implements the kernels for the single precision matrix/matrix
multiply operation (SGEMM).
This implementation uses SSE2 instructions.
--*/
#include "asmmacro.h"
#include "SgemmKernelCommon.h"
#include "FgemmKernelSse2Common.h"
.intel_syntax noprefix
.text
/*++
Macro Description:
This macro multiplies and accumulates for a 16xN block of the output matrix.
Arguments:
RowCount - Supplies the number of rows to process.
VectorOffset - Supplies the byte offset from matrix B to fetch elements.
Shuffle - Supplies the shuffle mask to extract the element from matrix A.
Implicit Arguments:
rsi - Supplies the address into the matrix B data.
xmm0-xmm1 - Supplies up to four elements loaded from matrix A and matrix A
plus one row.
xmm8-xmm15 - Supplies the block accumulators.
--*/
.macro ComputeBlockSseBy16 RowCount, VectorOffset, Shuffle
movaps xmm4,XMMWORD PTR [rsi+\VectorOffset\()]
movaps xmm5,XMMWORD PTR [rsi+\VectorOffset\()+16]
pshufd xmm2,xmm0,\Shuffle\()
.if \RowCount\() == 2
pshufd xmm3,xmm1,\Shuffle\()
movaps xmm6,xmm4
movaps xmm7,xmm5
.endif
mulps xmm4,xmm2
mulps xmm5,xmm2
addps xmm8,xmm4
addps xmm9,xmm5
.if \RowCount\() == 2
mulps xmm6,xmm3
mulps xmm7,xmm3
addps xmm12,xmm6
addps xmm13,xmm7
.endif
movaps xmm4,XMMWORD PTR [rsi+\VectorOffset\()+32]
movaps xmm5,XMMWORD PTR [rsi+\VectorOffset\()+48]
.if \RowCount\() == 2
movaps xmm6,xmm4
movaps xmm7,xmm5
.endif
mulps xmm4,xmm2
mulps xmm5,xmm2
addps xmm10,xmm4
addps xmm11,xmm5
.if \RowCount\() == 2
mulps xmm6,xmm3
mulps xmm7,xmm3
addps xmm14,xmm6
addps xmm15,xmm7
.endif
.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:
rdi - Supplies the address of matrix A.
rsi - Supplies the address of matrix B.
r11 - Supplies the address of matrix A.
r9 - Supplies the number of columns from matrix B and matrix C to iterate
over.
rdx - Supplies the address of matrix C.
rcx - Supplies the number of columns from matrix A and the number of rows
from matrix B to iterate over.
r10 - Supplies the length in bytes of a row from matrix A.
rax - Supplies the length in bytes of a row from matrix C.
r15 - Stores the ZeroMode argument from the stack frame.
--*/
.macro ProcessCountM RowCount, Fallthrough
.LProcessNextColumnLoop16xN\@:
EmitIfCountGE \RowCount\(), 1, "xorps xmm8,xmm8"
EmitIfCountGE \RowCount\(), 1, "xorps xmm9,xmm9"
EmitIfCountGE \RowCount\(), 1, "xorps xmm10,xmm10"
EmitIfCountGE \RowCount\(), 1, "xorps xmm11,xmm11"
EmitIfCountGE \RowCount\(), 2, "xorps xmm12,xmm12"
EmitIfCountGE \RowCount\(), 2, "xorps xmm13,xmm13"
EmitIfCountGE \RowCount\(), 2, "xorps xmm14,xmm14"
EmitIfCountGE \RowCount\(), 2, "xorps xmm15,xmm15"
mov rbp,rcx # reload CountK
sub rbp,4
jb .LProcessRemaining16xNBlocks\@
.LCompute16xNBlockBy4Loop\@:
EmitIfCountGE \RowCount\(), 1, "movups xmm0,XMMWORD PTR [rdi]"
EmitIfCountGE \RowCount\(), 2, "movups xmm1,XMMWORD PTR [rdi+r10]"
ComputeBlockSseBy16 2, 0, 0x00
ComputeBlockSseBy16 2, 16*4, 0x55
sub rsi,-32*4 # advance matrix B by 32 columns
ComputeBlockSseBy16 2, 0, 0xAA
ComputeBlockSseBy16 2, 16*4, 0xFF
sub rsi,-32*4 # advance matrix B by 32 columns
add rdi,4*4 # advance matrix A by 4 columns
sub rbp,4
jae .LCompute16xNBlockBy4Loop\@
.LProcessRemaining16xNBlocks\@:
add rbp,4 # correct for over-subtract above
jz .LOutput16xNBlock\@
.LCompute16xNBlockBy1Loop\@:
EmitIfCountGE \RowCount\(), 1, "movss xmm0,[rdi]"
EmitIfCountGE \RowCount\(), 2, "movss xmm1,[rdi+r10]"
ComputeBlockSseBy16 2, 0, 0x00
add rsi,16*4 # advance matrix B by 16 columns
add rdi,4 # advance matrix A by 1 column
dec rbp
jne .LCompute16xNBlockBy1Loop\@
.LOutput16xNBlock\@:
movss xmm2,.LFgemmKernelFrame_alpha[rsp]
shufps xmm2,xmm2,0
EmitIfCountGE \RowCount\(), 1, "mulps xmm8,xmm2"
# multiply by alpha
EmitIfCountGE \RowCount\(), 1, "mulps xmm9,xmm2"
EmitIfCountGE \RowCount\(), 1, "mulps xmm10,xmm2"
EmitIfCountGE \RowCount\(), 1, "mulps xmm11,xmm2"
EmitIfCountGE \RowCount\(), 2, "mulps xmm12,xmm2"
EmitIfCountGE \RowCount\(), 2, "mulps xmm13,xmm2"
EmitIfCountGE \RowCount\(), 2, "mulps xmm14,xmm2"
EmitIfCountGE \RowCount\(), 2, "mulps xmm15,xmm2"
sub r9,16
jb .LOutputPartial16xNBlock\@
AccumulateAndStoreBlock \RowCount\(), 4
add rdx,16*4 # advance matrix C by 16 columns
mov rdi,r11 # reload matrix A
test r9,r9
jnz .LProcessNextColumnLoop16xN\@
jmp .LExitKernel
//
// Output a partial 16xN block to the matrix.
//
.LOutputPartial16xNBlock\@:
add r9,16 # correct for over-subtract above
cmp r9,4
jb .LOutputPartialLessThan4xNBlock\@
cmp r9,8
jb .LOutputPartialLessThan8xNBlock\@
cmp r9,12
jb .LOutputPartialLessThan12xNBlock\@
AccumulateAndStoreBlock \RowCount\(), 3
and r9d,3 # check if remaining count is small
jz .LExitKernel
EmitIfCountGE \RowCount\(), 1, "movaps xmm8,xmm11"
# shift remaining elements down
EmitIfCountGE \RowCount\(), 2, "movaps xmm12,xmm15"
add rdx,12*4 # advance matrix C by 12 columns
jmp .LOutputPartialLessThan4xNBlock\@
.LOutputPartialLessThan12xNBlock\@:
AccumulateAndStoreBlock \RowCount\(), 2
and r9d,3 # check if remaining count is small
jz .LExitKernel
EmitIfCountGE \RowCount\(), 1, "movaps xmm8,xmm10"
# shift remaining elements down
EmitIfCountGE \RowCount\(), 2, "movaps xmm12,xmm14"
add rdx,8*4 # advance matrix C by 8 columns
jmp .LOutputPartialLessThan4xNBlock\@
.LOutputPartialLessThan8xNBlock\@:
AccumulateAndStoreBlock \RowCount\(), 1
and r9d,3 # check if remaining count is small
jz .LExitKernel
EmitIfCountGE \RowCount\(), 1, "movaps xmm8,xmm9"
# shift remaining elements down
EmitIfCountGE \RowCount\(), 2, "movaps xmm12,xmm13"
add rdx,4*4 # advance matrix C by 4 columns
.LOutputPartialLessThan4xNBlock\@:
test r9d,2
jz .LOutputPartial1xNBlock\@
test r15b,r15b # ZeroMode?
jnz .LSkipAccumulateOutput2xN\@
EmitIfCountGE \RowCount\(), 1, "movsd xmm0,QWORD PTR [rdx]"
EmitIfCountGE \RowCount\(), 2, "movsd xmm1,QWORD PTR [rdx+rax]"
EmitIfCountGE \RowCount\(), 1, "addps xmm8,xmm0"
EmitIfCountGE \RowCount\(), 2, "addps xmm12,xmm1"
.LSkipAccumulateOutput2xN\@:
EmitIfCountGE \RowCount\(), 1, "movsd QWORD PTR [rdx],xmm8"
EmitIfCountGE \RowCount\(), 2, "movsd QWORD PTR [rdx+rax],xmm12"
test r9d,1 # check if remaining count is odd
jz .LExitKernel
EmitIfCountGE \RowCount\(), 1, "movhlps xmm8,xmm8"
# shift third element down
EmitIfCountGE \RowCount\(), 2, "movhlps xmm12,xmm12"
add rdx,2*4 # advance matrix C by 2 columns
.LOutputPartial1xNBlock\@:
test r15b,r15b # ZeroMode?
jnz .LSkipAccumulateOutput1xN\@
EmitIfCountGE \RowCount\(), 1, "addss xmm8,[rdx]"
EmitIfCountGE \RowCount\(), 2, "addss xmm12,[rdx+rax]"
.LSkipAccumulateOutput1xN\@:
EmitIfCountGE \RowCount\(), 1, "movss [rdx],xmm8"
EmitIfCountGE \RowCount\(), 2, "movss [rdx+rax],xmm12"
.ifb \Fallthrough\()
jmp .LExitKernel
.endif
.endm
//
// Generate the GEMM kernel.
//
FgemmKernelSse2Function MlasGemmFloatKernelSse
.end