1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00
Files
opencv/3rdparty/mlas/lib/x86_64/SgemmKernelM1TransposeBAvx.S
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

276 lines
8.1 KiB
ArmAsm

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
Module Name:
SgemmKernelM1TransposeBAvx.s
Abstract:
This module implements the kernels for the single precision matrix/matrix
multiply operation (SGEMM). This handles the special case of M=1.
This implementation uses AVX instructions.
--*/
#include "asmmacro.h"
.intel_syntax noprefix
.text
/*++
Routine Description:
This routine is an inner kernel to compute matrix multiplication for a
set of rows. This handles the special case of M=1.
The elements in matrix B are transposed.
Arguments:
A (rdi) - Supplies the address of matrix A.
B (rsi) - Supplies the address of matrix B. The elements are transposed.
C (rdx) - Supplies the address of matrix C.
CountK (rcx) - Supplies the number of columns from matrix A and the number
of columns from matrix B to iterate over.
CountN (r8) - Supplies the number of rows from matrix B and the number of
columns from matrix C to iterate over.
ldb (r9) - Supplies the first dimension of matrix B.
Beta (xmm0) - Supplies the scalar beta multiplier (see SGEMM definition).
Return Value:
None.
--*/
FUNCTION_ENTRY MlasSgemmKernelM1TransposeBAvx
push rbx
shl r9,2 # convert ldb to bytes
mov r10,rdi
mov r11,rsi
//
// Compute the results mask for zeroing or accumulate mode.
//
vxorps xmm1,xmm1,xmm1
vcmpeqss xmm0,xmm1,xmm0
vshufps xmm0,xmm0,xmm0,0
//
// Compute the conditional load/store mask for an unaligned CountK.
//
mov eax,ecx
and eax,7
vmovd xmm7,eax
vshufps xmm7,xmm7,xmm7,0
vpcmpgtd xmm6,xmm7,XMMWORD PTR C_UNDERSCORE(MlasMaskMoveAvx)[rip+16]
vpcmpgtd xmm7,xmm7,XMMWORD PTR C_UNDERSCORE(MlasMaskMoveAvx)[rip]
vinsertf128 ymm7,ymm7,xmm6,1
//
// Process 4 rows of the matrices in a loop.
//
sub r8,4
jb .LProcessRemainingCountN
.LProcessRowLoop4:
vxorps xmm2,xmm2,xmm2 # clear row accumulators
vxorps xmm3,xmm3,xmm3
vxorps xmm4,xmm4,xmm4
vxorps xmm5,xmm5,xmm5
mov rdi,r10 # reload matrix A
mov rsi,r11 # reload matrix B
mov rax,rcx # reload CountK
lea r11,[rsi+r9*4] # advance matrix B by 4 rows
sub rax,8
jb .LProcessRemainingCountK4
.LProcessColumnLoop4:
lea rbx,[rsi+r9*2] # compute matrix B plus 2 rows
vmovups ymm1,YMMWORD PTR [rdi]
vmulps ymm6,ymm1,YMMWORD PTR [rsi]
vaddps ymm2,ymm2,ymm6
vmulps ymm6,ymm1,YMMWORD PTR [rsi+r9]
vaddps ymm3,ymm3,ymm6
vmulps ymm6,ymm1,YMMWORD PTR [rbx]
vaddps ymm4,ymm4,ymm6
vmulps ymm6,ymm1,YMMWORD PTR [rbx+r9]
vaddps ymm5,ymm5,ymm6
add rdi,8*4 # advance matrix A by 8 columns
add rsi,8*4 # advance matrix B by 8 columns
sub rax,8
jae .LProcessColumnLoop4
.LProcessRemainingCountK4:
test al,7 # test for unaligned columns
jz .LOutput4x1Block
lea rbx,[rsi+r9*2] # compute matrix B plus 2 rows
vmaskmovps ymm1,ymm7,YMMWORD PTR [rdi]
vmaskmovps ymm6,ymm7,YMMWORD PTR [rsi]
vmulps ymm6,ymm1,ymm6
vaddps ymm2,ymm2,ymm6
vmaskmovps ymm6,ymm7,YMMWORD PTR [rsi+r9]
vmulps ymm6,ymm1,ymm6
vaddps ymm3,ymm3,ymm6
vmaskmovps ymm6,ymm7,YMMWORD PTR [rbx]
vmulps ymm6,ymm1,ymm6
vaddps ymm4,ymm4,ymm6
vmaskmovps ymm6,ymm7,YMMWORD PTR [rbx+r9]
vmulps ymm6,ymm1,ymm6
vaddps ymm5,ymm5,ymm6
//
// Reduce and output the row accumulators.
//
.LOutput4x1Block:
vunpcklps ymm6,ymm2,ymm3 # transpose row accumulators
vunpckhps ymm1,ymm2,ymm3
vunpcklps ymm2,ymm4,ymm5
vunpckhps ymm3,ymm4,ymm5
vunpcklpd ymm4,ymm6,ymm2
vunpckhpd ymm5,ymm6,ymm2
vaddps ymm4,ymm4,ymm5
vunpcklpd ymm6,ymm1,ymm3
vunpckhpd ymm2,ymm1,ymm3
vaddps ymm4,ymm4,ymm6
vaddps ymm4,ymm4,ymm2
vextractf128 xmm5,ymm4,1
vaddps xmm4,xmm4,xmm5
vandnps xmm6,xmm0,XMMWORD PTR [rdx]
vaddps xmm4,xmm4,xmm6
vmovups XMMWORD PTR [rdx],xmm4
add rdx,4*4 # advance matrix C by 4 columns
sub r8,4
jae .LProcessRowLoop4
.LProcessRemainingCountN:
test r8d,2
jnz .LProcessRowLoop2
test r8d,1
jnz .LProcessRowLoop1
.LExitKernel:
vzeroupper
pop rbx
ret
//
// Process 2 rows of the matrices.
//
.LProcessRowLoop2:
vxorps xmm2,xmm2,xmm2 # clear row accumulators
vxorps xmm3,xmm3,xmm3
mov rdi,r10 # reload matrix A
mov rsi,r11 # reload matrix B
mov rax,rcx # reload CountK
lea r11,[rsi+r9*2] # advance matrix B by 2 rows
sub rax,8
jb .LProcessRemainingCountK2
.LProcessColumnLoop2:
vmovups ymm1,YMMWORD PTR [rdi]
vmulps ymm6,ymm1,YMMWORD PTR [rsi]
vaddps ymm2,ymm2,ymm6
vmulps ymm6,ymm1,YMMWORD PTR [rsi+r9]
vaddps ymm3,ymm3,ymm6
add rdi,8*4 # advance matrix A by 8 columns
add rsi,8*4 # advance matrix B by 8 columns
sub rax,8
jae .LProcessColumnLoop2
.LProcessRemainingCountK2:
test al,7 # test for unaligned columns
jz .LOutput2x1Block
vmaskmovps ymm1,ymm7,YMMWORD PTR [rdi]
vmaskmovps ymm6,ymm7,YMMWORD PTR [rsi]
vmulps ymm6,ymm1,ymm6
vaddps ymm2,ymm2,ymm6
vmaskmovps ymm6,ymm7,YMMWORD PTR [rsi+r9]
vmulps ymm6,ymm1,ymm6
vaddps ymm3,ymm3,ymm6
//
// Reduce and output the row accumulators.
//
.LOutput2x1Block:
vunpcklps ymm4,ymm2,ymm3 # reduce row accumulators
vunpckhps ymm2,ymm2,ymm3
vaddps ymm2,ymm2,ymm4
vextractf128 xmm4,ymm2,1
vaddps xmm2,xmm2,xmm4
vmovhlps xmm4,xmm2,xmm2
vaddps xmm2,xmm2,xmm4
vmovsd xmm3,QWORD PTR [rdx]
vandnps xmm3,xmm0,xmm3
vaddps xmm2,xmm2,xmm3
vmovsd QWORD PTR [rdx],xmm2
add rdx,2*4 # advance matrix C by 2 columns
test r8d,1
jz .LExitKernel
//
// Process 1 row of the matrices.
//
.LProcessRowLoop1:
vxorps xmm2,xmm2,xmm2 # clear row accumulators
mov rdi,r10 # reload matrix A
mov rsi,r11 # reload matrix B
mov rax,rcx # reload CountK
sub rax,8
jb .LProcessRemainingCountK1
.LProcessColumnLoop1:
vmovups ymm1,YMMWORD PTR [rdi]
vmulps ymm6,ymm1,YMMWORD PTR [rsi]
vaddps ymm2,ymm2,ymm6
add rdi,8*4 # advance matrix A by 8 columns
add rsi,8*4 # advance matrix B by 8 columns
sub rax,8
jae .LProcessColumnLoop1
.LProcessRemainingCountK1:
test al,7 # test for unaligned columns
jz .LOutput1x1Block
vmaskmovps ymm1,ymm7,YMMWORD PTR [rdi]
vmaskmovps ymm6,ymm7,YMMWORD PTR [rsi]
vmulps ymm6,ymm1,ymm6
vaddps ymm2,ymm2,ymm6
//
// Reduce and output the row accumulators.
//
.LOutput1x1Block:
vhaddps ymm2,ymm2,ymm2 # reduce row accumulators
vhaddps ymm2,ymm2,ymm2
vextractf128 xmm4,ymm2,1
vaddss xmm2,xmm2,xmm4
vmovss xmm3,DWORD PTR [rdx]
vandnps xmm3,xmm0,xmm3
vaddss xmm2,xmm2,xmm3
vmovss DWORD PTR [rdx],xmm2
jmp .LExitKernel
.end