xref: /aosp_15_r20/external/gemmlowp/internal/kernel_avx.h (revision 5f39d1b313f0528e11bae88b3029b54b9e1033e7)
1*5f39d1b3SJooyung Han //
2*5f39d1b3SJooyung Han // Licensed under the Apache License, Version 2.0 (the "License");
3*5f39d1b3SJooyung Han // you may not use this file except in compliance with the License.
4*5f39d1b3SJooyung Han // You may obtain a copy of the License at
5*5f39d1b3SJooyung Han //
6*5f39d1b3SJooyung Han //     http://www.apache.org/licenses/LICENSE-2.0
7*5f39d1b3SJooyung Han //
8*5f39d1b3SJooyung Han // Unless required by applicable law or agreed to in writing, software
9*5f39d1b3SJooyung Han // distributed under the License is distributed on an "AS IS" BASIS,
10*5f39d1b3SJooyung Han // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11*5f39d1b3SJooyung Han // See the License for the specific language governing permissions and
12*5f39d1b3SJooyung Han // limitations under the License.
13*5f39d1b3SJooyung Han 
14*5f39d1b3SJooyung Han // kernel_SSE.h: a collection of Intel SSE optimized kernels.
15*5f39d1b3SJooyung Han // Check in kernel_default.h which one(s) are actually used by default.
16*5f39d1b3SJooyung Han // Others are mere experiments; they are still covered by tests
17*5f39d1b3SJooyung Han // in case they might be useful some day.
18*5f39d1b3SJooyung Han //
19*5f39d1b3SJooyung Han 
20*5f39d1b3SJooyung Han #ifndef GEMMLOWP_INTERNAL_KERNEL_AVX_H_
21*5f39d1b3SJooyung Han #define GEMMLOWP_INTERNAL_KERNEL_AVX_H_
22*5f39d1b3SJooyung Han 
23*5f39d1b3SJooyung Han #include "kernel.h"
24*5f39d1b3SJooyung Han 
25*5f39d1b3SJooyung Han #include <string.h>
26*5f39d1b3SJooyung Han #include <cassert>
27*5f39d1b3SJooyung Han 
28*5f39d1b3SJooyung Han namespace gemmlowp {
29*5f39d1b3SJooyung Han 
30*5f39d1b3SJooyung Han #ifdef GEMMLOWP_AVX2_64
31*5f39d1b3SJooyung Han struct AVX2_64_Kernel24x8Depth2 : KernelBase {
32*5f39d1b3SJooyung Han   typedef KernelFormat<KernelSideFormat<CellFormat<8, 2, CellOrder::WidthMajor>, 3>,
33*5f39d1b3SJooyung Han                        KernelSideFormat<CellFormat<4, 2, CellOrder::WidthMajor>, 1>>
34*5f39d1b3SJooyung Han       Format;
35*5f39d1b3SJooyung Han 
NameAVX2_64_Kernel24x8Depth236*5f39d1b3SJooyung Han   const char *Name() const override { return "AVX, 24x8, depth 2"; }
37*5f39d1b3SJooyung Han 
RunAVX2_64_Kernel24x8Depth238*5f39d1b3SJooyung Han   void Run(std::int32_t *dst_ptr, std::size_t dst_row_stride, std::size_t dst_col_stride,
39*5f39d1b3SJooyung Han            const std::uint8_t *lhs_ptr, const std::uint8_t *rhs_ptr, std::size_t start_depth,
40*5f39d1b3SJooyung Han            std::size_t run_depth) const override {
41*5f39d1b3SJooyung Han     ScopedProfilingLabel label("optimized kernel");
42*5f39d1b3SJooyung Han     assert(dst_row_stride == 1);
43*5f39d1b3SJooyung Han     const std::int64_t run_depth_cells = run_depth / Format::kDepth;
44*5f39d1b3SJooyung Han     const std::int64_t dst_col_stride_q = dst_col_stride;
45*5f39d1b3SJooyung Han 
46*5f39d1b3SJooyung Han     /* Main loop */
47*5f39d1b3SJooyung Han 
48*5f39d1b3SJooyung Han     // A 2x8 cell of Rhs is stored in 16bit in ymm1 .
49*5f39d1b3SJooyung Han     // A 24x2 block of 3 8x2 cells Lhs is stored in 16bit in ymm0, replaced
50*5f39d1b3SJooyung Han     // every Iteration.
51*5f39d1b3SJooyung Han     // A 8x8 block of accumulators is stored in 32bit in xmm4--xmm15.
52*5f39d1b3SJooyung Han     //
53*5f39d1b3SJooyung Han     //                   +-------+-------+-------+-------+
54*5f39d1b3SJooyung Han     //                   |ymm1[0]        |ymm2[2]        |
55*5f39d1b3SJooyung Han     //              Rhs  +-------+---------------+-------+
56*5f39d1b3SJooyung Han     //                   |ymm1[1]        |ymm1[4]        |
57*5f39d1b3SJooyung Han     //                   +-------+-------+-------+-------+
58*5f39d1b3SJooyung Han     //
59*5f39d1b3SJooyung Han     //                   |       |       |       |       |
60*5f39d1b3SJooyung Han     //
61*5f39d1b3SJooyung Han     //    Lhs            |       |       |       |       |
62*5f39d1b3SJooyung Han     //
63*5f39d1b3SJooyung Han     //  +--+--+ - - - -  +-------+-------+-------+-------+
64*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm4  | ymm5  | ymm6  | ymm7  |
65*5f39d1b3SJooyung Han     //  |ymm0 | (Iter1)  | ymm4  | ymm5  | ymm6  | ymm7  |
66*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm4  | ymm5  | ymm6  | ymm7  |
67*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm4  | ymm5  | ymm6  | ymm7  |
68*5f39d1b3SJooyung Han     //  +--+--+ - - - -  +-------+-------+-------+-------+
69*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm8  | ymm9  | ymm10 | ymm11 |
70*5f39d1b3SJooyung Han     //  |ymm0 | (Iter2)  | ymm8  | ymm9  | ymm10 | ymm11 |
71*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm8  | ymm9  | ymm10 | ymm11 |
72*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm8  | ymm9  | ymm10 | ymm11 |
73*5f39d1b3SJooyung Han     //  +--+--+ - - - -  +-------+-------+-------+-------+
74*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm12 | ymm13 | ymm14 | ymm15 |
75*5f39d1b3SJooyung Han     //  |ymm0 | (Iter3)  | ymm12 | ymm13 | ymm14 | ymm15 |
76*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm12 | ymm13 | ymm14 | ymm15 |
77*5f39d1b3SJooyung Han     //  |ymm0 |          | ymm12 | ymm13 | ymm14 | ymm15 |
78*5f39d1b3SJooyung Han     //  +--+--+ - - - -  +-------+-------+-------+-------+
79*5f39d1b3SJooyung Han     //
80*5f39d1b3SJooyung Han     //                              Accumulator
81*5f39d1b3SJooyung Han 
82*5f39d1b3SJooyung Han     asm volatile(
83*5f39d1b3SJooyung Han         // Set registers for destination
84*5f39d1b3SJooyung Han         "movq  %[dst_col_stride_q], %%r12\n\t"  // stride is r12
85*5f39d1b3SJooyung Han         "shlq $2, %%r12\n\t"                    // set stride dword
86*5f39d1b3SJooyung Han         "leaq (%%r12,%%r12,0x2), %%r13\n\t"     // load stride aligned r13
87*5f39d1b3SJooyung Han 
88*5f39d1b3SJooyung Han         // Set accumulators to zero.
89*5f39d1b3SJooyung Han         "vpxor %%ymm4, %%ymm4, %%ymm4 \n\t"    // zero accumulators
90*5f39d1b3SJooyung Han         "vpxor %%ymm5, %%ymm5, %%ymm5 \n\t"    // zero accumulators
91*5f39d1b3SJooyung Han         "vpxor %%ymm6, %%ymm6, %%ymm6 \n\t"    // zero accumulators
92*5f39d1b3SJooyung Han         "vpxor %%ymm7, %%ymm7, %%ymm7 \n\t"    // zero accumulators
93*5f39d1b3SJooyung Han         "vpxor %%ymm8, %%ymm8, %%ymm8 \n\t"    // zero accumulators
94*5f39d1b3SJooyung Han         "vpxor %%ymm9, %%ymm9, %%ymm9 \n\t"    // zero accumulators
95*5f39d1b3SJooyung Han         "vpxor %%ymm10, %%ymm10, %%ymm10\n\t"  // zero accumulators
96*5f39d1b3SJooyung Han         "vpxor %%ymm11, %%ymm11, %%ymm11\n\t"  // zero accumulators
97*5f39d1b3SJooyung Han         "vpxor %%ymm12, %%ymm12, %%ymm12\n\t"  // zero accumulators
98*5f39d1b3SJooyung Han         "vpxor %%ymm13, %%ymm13, %%ymm13\n\t"  // zero accumulators
99*5f39d1b3SJooyung Han         "vpxor %%ymm14, %%ymm14, %%ymm14\n\t"  // zero accumulators
100*5f39d1b3SJooyung Han         "vpxor %%ymm15, %%ymm15, %%ymm15\n\t"  // zero accumulators
101*5f39d1b3SJooyung Han 
102*5f39d1b3SJooyung Han         "movq  %[run_depth_cells], %%r14 \n\t"  // load cell depth r14
103*5f39d1b3SJooyung Han         "subq $2, %%r14 \n\t"                   // cell depth is 2
104*5f39d1b3SJooyung Han         "js outerLoop1%= \n\t"                  // outerloop for matrix
105*5f39d1b3SJooyung Han 
106*5f39d1b3SJooyung Han         // Loop for K unrolled by 4
107*5f39d1b3SJooyung Han         "outerLoop2%=: \n\t"  // outer loop unroll
108*5f39d1b3SJooyung Han 
109*5f39d1b3SJooyung Han         // K = 0,1,2,3
110*5f39d1b3SJooyung Han         // RHS cell to ymm1
111*5f39d1b3SJooyung Han 
112*5f39d1b3SJooyung Han         // lower half
113*5f39d1b3SJooyung Han         "vpmovzxbw (%[rhs_ptr]), %%ymm1 \n\t"  // mov rhs to ymm1
114*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"
115*5f39d1b3SJooyung Han         // LHS cell elements 0 and 1
116*5f39d1b3SJooyung Han         "vpmovzxbw 0x00(%[lhs_ptr]), %%ymm0\n\t"  // mov lhs to ymm0
117*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2     \n\t"    // move rhs 0 element to all ymm2
118*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3     \n\t"    // move rhs 1 element to all ymm3
119*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2 \n\t"    // mul add lhs rhs0 into ymm2
120*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3 \n\t"    // mul add lhs rhs1 into ymm3
121*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm4, %%ymm4   \n\t"    // add muladd lhs + rhs0 into ymm4
122*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm5, %%ymm5   \n\t"    // add muladd lhs + rhs1 into ymm5
123*5f39d1b3SJooyung Han         // LHS cell elements 2 and 3
124*5f39d1b3SJooyung Han         "vpshufd $0xaa, %%ymm1, %%ymm2   \n\t"  // move rhs 2 element to all ymm2
125*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2 \n\t"  // mul add lhs rh3 into ymm2
126*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3     \n\t"  // mov rhs 3 element into all ymm3
127*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3 \n\t"  // mul add lhs rh4 into ymm3
128*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm6, %%ymm6   \n\t"  // add muladd lhs + rhs2 into ymm6
129*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm7, %%ymm7   \n\t"  // add muladd lhs + rhs3 into ymm7
130*5f39d1b3SJooyung Han 
131*5f39d1b3SJooyung Han         // cache prefect lhs //see if it works better?
132*5f39d1b3SJooyung Han         //"prefetcht0 0x80(%[lhs_ptr]) \n\t" //prefetch cache lines
133*5f39d1b3SJooyung Han         "vpmovzxbw (%[rhs_ptr]), %%ymm1 \n\t"  // mov rhs to ymm1
134*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"
135*5f39d1b3SJooyung Han 
136*5f39d1b3SJooyung Han         // K = 5,6,7,8
137*5f39d1b3SJooyung Han         // next LHS cell elements 0 and 1
138*5f39d1b3SJooyung Han         "vpmovzxbw 0x10(%[lhs_ptr]), %%ymm0 \n\t"  // mov lhs to ymm0
139*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2        \n\t"  // mov rhs 0 element to all ymm2
140*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3        \n\t"  // mov rhs 1 element to all ymm3
141*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // mul add lhs rhs0 into ymm2
142*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // mul add lhs rhs1 into ymm3
143*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm8, %%ymm8      \n\t"  // add muladd lhs + rhs0 into ymm8
144*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm9, %%ymm9      \n\t"  // add muladd lhs + rhs1 into ymm9
145*5f39d1b3SJooyung Han         // next LHS cell elements 2 and 3
146*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2        \n\t"  // mov rhs 2 element to all ymm2
147*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3        \n\t"  // mov rhs 3 element to all ymm3
148*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // mul add lhs rhs2 into ymm2
149*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // mul add lhs rhs3 into ymm3
150*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm10, %%ymm10    \n\t"  // add muladd lhs + rhs2 into ymm10
151*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm11, %%ymm11    \n\t"  // add muladd lhs + rhs3 into ymm11
152*5f39d1b3SJooyung Han 
153*5f39d1b3SJooyung Han         // rhs lower half
154*5f39d1b3SJooyung Han         "vpmovzxbw (%[rhs_ptr]), %%ymm1 \n\t"  // mov rhs to ymm1
155*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"     // duplcate lower 16
156*5f39d1b3SJooyung Han 
157*5f39d1b3SJooyung Han         // next LHS cell elements 0 and 1
158*5f39d1b3SJooyung Han         "vpmovzxbw 0x20(%[lhs_ptr]), %%ymm0 \n\t"    // mov lhs to ymm0
159*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2        \n\t"    // mov rhs 0 element to all ymm2
160*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3        \n\t"    // mov rhs 1 element to all ymm3
161*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"    // mul add lhs rhs0 into ymm2
162*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"    // mul add lhs rhs1 into ymm3
163*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm12, %%ymm12      \n\t"  // add muladd lhs + rhs0 into ymm8
164*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm13, %%ymm13      \n\t"  // add muladd lhs + rhs1 into ymm9
165*5f39d1b3SJooyung Han 
166*5f39d1b3SJooyung Han         // cache prefetch rhs //see if it works better?
167*5f39d1b3SJooyung Han         //"prefetcht0 0x80(%[rhs_ptr]) \n\t"
168*5f39d1b3SJooyung Han 
169*5f39d1b3SJooyung Han         // next LHS cell elements 2 and 3
170*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2        \n\t"  // mov rhs 2 element to all ymm2
171*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3        \n\t"  // mov rhs 3 element to all ymm3
172*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // mul add lhs rhs2 into ymm2
173*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // mul add lhs rhs3 into ymm3
174*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm14, %%ymm14    \n\t"  // add muladd lhs + rhs2 into ymm10
175*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm15, %%ymm15    \n\t"  // add muladd lhs + rhs3 into ymm11
176*5f39d1b3SJooyung Han 
177*5f39d1b3SJooyung Han         // current result in ymm4, ymm5, ymm6, ymm7, ymm8, ymm9, ymm10 ymm11 ymm12 ymm13 ymm14 ymm15
178*5f39d1b3SJooyung Han 
179*5f39d1b3SJooyung Han         // rhs+10 lower half
180*5f39d1b3SJooyung Han         "vpmovzxbw 0x08(%[rhs_ptr]), %%ymm1 \n\t"  // mov rhs to ymm1
181*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"
182*5f39d1b3SJooyung Han         // next LHS cell elements 0 and 1
183*5f39d1b3SJooyung Han         "vpmovzxbw 0x30(%[lhs_ptr]), %%ymm0 \n\t"  // mov lhs to ymm0
184*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2        \n\t"  // move rhs 0 element to ymm2
185*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3        \n\t"  // move rhs 1 element to ymm3
186*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // muladd lhs rhs0 into ymm2
187*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // muladd lhs rhs1 into ymm3
188*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm4, %%ymm4      \n\t"  // accumulate to ymm4
189*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm5, %%ymm5      \n\t"  // accumulate to ymm5
190*5f39d1b3SJooyung Han         // next LHS cell elements 2 and 3
191*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2        \n\t"  // mov rhs 2 element to ymm2
192*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3        \n\t"  // mov rhs 3 element to ymm2
193*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // mul add lhs rhs2 into ymm2
194*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // mull add lhs rhs3 into ymm3
195*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm6, %%ymm6      \n\t"  // add lhs rhs2 to ymm6
196*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm7, %%ymm7      \n\t"  // add lhs rhs3 to ymm7
197*5f39d1b3SJooyung Han 
198*5f39d1b3SJooyung Han         // rhs+10 lower half
199*5f39d1b3SJooyung Han         "vpmovzxbw 0x08(%[rhs_ptr]), %%ymm1 \n\t"  // mov rhs to ymm1
200*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"
201*5f39d1b3SJooyung Han 
202*5f39d1b3SJooyung Han         // next LHS cell elements 4 and 5
203*5f39d1b3SJooyung Han         "vpmovzxbw 0x40(%[lhs_ptr]), %%ymm0 \n\t"  // mov lhs to ymm0
204*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2        \n\t"  // move rhs 0 element to ymm2
205*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3        \n\t"  // move rhs 1 element to ymm3
206*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // muladd lhs rhs0 into ymm2
207*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // muladd lhs rhs1 into ymm3
208*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm8, %%ymm8      \n\t"  // accumulate to ymm8
209*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm9, %%ymm9      \n\t"  // accumulate to ymm9
210*5f39d1b3SJooyung Han         // next LHS cell elements 6 and 7
211*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2        \n\t"  // mov rhs 2 element to ymm2
212*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3        \n\t"  // mov rhs 3 element to ymm2
213*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // mul add lhs rhs2 into ymm2
214*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // mull add lhs rhs3 into ymm3
215*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm10, %%ymm10    \n\t"  // add lhs rhs2 to ymm10
216*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm11, %%ymm11    \n\t"  // add lhs rhs3 to ymm11
217*5f39d1b3SJooyung Han 
218*5f39d1b3SJooyung Han         "vpmovzxbw 0x08(%[rhs_ptr]), %%ymm1 \n\t"  // mov rhs to ymm1
219*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"
220*5f39d1b3SJooyung Han         // next LHS cell elements 9 and 10
221*5f39d1b3SJooyung Han         "vpmovzxbw 0x50(%[lhs_ptr]), %%ymm0 \n\t"  // mov lhs to ymm0
222*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2        \n\t"  // move rhs 0 element to ymm2
223*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3        \n\t"  // move rhs 1 element to ymm3
224*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // muladd lhs rhs0 into ymm2
225*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // muladd lhs rhs1 into ymm3
226*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm12, %%ymm12    \n\t"  // accumulate to ymm12
227*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm13, %%ymm13    \n\t"  // accumulate to ymm13
228*5f39d1b3SJooyung Han 
229*5f39d1b3SJooyung Han         // next LHS cell elements 11 and 12
230*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2        \n\t"  // mov rhs 2 element to ymm2
231*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3        \n\t"  // mov rhs 3 element to ymm2
232*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2    \n\t"  // mul add lhs rhs2 into ymm2
233*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3    \n\t"  // mull add lhs rhs3 into ymm3
234*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm14, %%ymm14    \n\t"  // add lhs rhs2 to ymm14
235*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm15, %%ymm15    \n\t"  // add lhs rhs3 to ymm15
236*5f39d1b3SJooyung Han 
237*5f39d1b3SJooyung Han         // completed rhs+10
238*5f39d1b3SJooyung Han         "addq $0x60, %[lhs_ptr]             \n\t"  // increment stride lhs
239*5f39d1b3SJooyung Han         "addq $0x10, %[rhs_ptr]             \n\t"  // increment stride rhs
240*5f39d1b3SJooyung Han 
241*5f39d1b3SJooyung Han         "subq $2, %[run_depth_cells] \n\t"
242*5f39d1b3SJooyung Han         "ja outerLoop2%= \n\t"
243*5f39d1b3SJooyung Han 
244*5f39d1b3SJooyung Han         "movq %[run_depth_cells], %%r14 \n\t"
245*5f39d1b3SJooyung Han         "decq %%r14 \n\t"
246*5f39d1b3SJooyung Han         "js finish%= \n\t"
247*5f39d1b3SJooyung Han 
248*5f39d1b3SJooyung Han         // Loop for K unrolled by 2
249*5f39d1b3SJooyung Han         "outerLoop1%=: \n\t"
250*5f39d1b3SJooyung Han 
251*5f39d1b3SJooyung Han         // rhs lower
252*5f39d1b3SJooyung Han         "vpmovzxbw (%[rhs_ptr]), %%ymm1 \n\t"  // get rhs into ymm1
253*5f39d1b3SJooyung Han         "vpermq $0x44,%%ymm1, %%ymm1 \n\t"
254*5f39d1b3SJooyung Han 
255*5f39d1b3SJooyung Han         // LHS cell
256*5f39d1b3SJooyung Han         "vpmovzxbw (%[lhs_ptr]), %%ymm0  \n\t"      // lhs in into ymm0
257*5f39d1b3SJooyung Han         "vpshufd $0x00,%%ymm1,%%ymm2         \n\t"  // rhs element 0 into ymm2
258*5f39d1b3SJooyung Han         "vpshufd $0x55,%%ymm1,%%ymm3         \n\t"  // rhs element 1 into ymm3
259*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2     \n\t"  // muladd lhs rhs element 0 ymm2
260*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3     \n\t"  // muladd lhs rhs element 1 ymm3
261*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm4, %%ymm4       \n\t"  // acc element 0 ymm4
262*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm5, %%ymm5       \n\t"  // acc element 1 ymm5
263*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2         \n\t"  // rhs element 2 into ymm2
264*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3         \n\t"  // rhs element 3 into ymm3
265*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2     \n\t"  // muladd lhs rhs element 2 ymm2
266*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3     \n\t"  // muladd lhs rhs element 3 ymm3
267*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm6, %%ymm6       \n\t"  // acc element 2 into ymm6
268*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm7, %%ymm7       \n\t"  // acc element 3 into ymm7
269*5f39d1b3SJooyung Han 
270*5f39d1b3SJooyung Han         // lhs+10
271*5f39d1b3SJooyung Han         "vpmovzxbw 0x10(%[lhs_ptr]), %%ymm0  \n\t"  // lhs in into ymm0
272*5f39d1b3SJooyung Han         "vpshufd $0x00, %%ymm1, %%ymm2       \n\t"  // rhs element 0 into ymm2
273*5f39d1b3SJooyung Han         "vpshufd $0x55, %%ymm1, %%ymm3       \n\t"  // rhs element 1 into ymm3
274*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2     \n\t"  // muladd lhs rhs element 0 ymm2
275*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3     \n\t"  // muladd lhs rhs element 1 ymm3
276*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm8, %%ymm8       \n\t"  // acc element 0 ymm8
277*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm9, %%ymm9       \n\t"  // acc element 1 ymm9
278*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2         \n\t"  // rhs element 2 into ymm2
279*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3         \n\t"  // rhs element 3 into ymm3
280*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2     \n\t"  // muladd lhs rhs element 2 ymm2
281*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3     \n\t"  // muladd lhs rhs element 3 ymm3
282*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm10, %%ymm10     \n\t"  // acc element 2 into ymm10
283*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm11, %%ymm11     \n\t"  // acc element 3 into ymm11
284*5f39d1b3SJooyung Han 
285*5f39d1b3SJooyung Han         "vpmovzxbw 0x20(%[lhs_ptr]), %%ymm0  \n\t"
286*5f39d1b3SJooyung Han         "vpshufd $0x00, %%ymm1, %%ymm2       \n\t"  // rhs element 0 into ymm2
287*5f39d1b3SJooyung Han         "vpshufd $0x55, %%ymm1, %%ymm3       \n\t"  // rhs element 1 into ymm3
288*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2     \n\t"  // muladd lhs rhs element 0 ymm2
289*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3     \n\t"  // muladd lhs rhs element 1 ymm3
290*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm12, %%ymm12     \n\t"  // acc element 0 ymm12
291*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm13, %%ymm13     \n\t"  // acc element 1 ymm13
292*5f39d1b3SJooyung Han         "vpshufd $0xaa,%%ymm1,%%ymm2         \n\t"  // rhs element 2 into ymm2
293*5f39d1b3SJooyung Han         "vpshufd $0xff,%%ymm1,%%ymm3         \n\t"  // rhs element 3 into ymm3
294*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm2, %%ymm2     \n\t"  // muladd lhs rhs element 2 ymm2
295*5f39d1b3SJooyung Han         "vpmaddwd %%ymm0, %%ymm3, %%ymm3     \n\t"  // muladd lhs rhs element 3 ymm3
296*5f39d1b3SJooyung Han         "vpaddd %%ymm2, %%ymm14, %%ymm14     \n\t"  // acc element 2 into ymm14
297*5f39d1b3SJooyung Han         "vpaddd %%ymm3, %%ymm15, %%ymm15     \n\t"  // acc element 3 into ymm15
298*5f39d1b3SJooyung Han 
299*5f39d1b3SJooyung Han         // update matrix pointers
300*5f39d1b3SJooyung Han         "addq $0x30, %[lhs_ptr]              \n\t"
301*5f39d1b3SJooyung Han         "addq $0x08, %[rhs_ptr]              \n\t"
302*5f39d1b3SJooyung Han 
303*5f39d1b3SJooyung Han         "decq %[run_depth_cells]             \n\t"
304*5f39d1b3SJooyung Han         "jnz outerLoop1%=                    \n\t"
305*5f39d1b3SJooyung Han 
306*5f39d1b3SJooyung Han         "finish%=:\n\t"
307*5f39d1b3SJooyung Han 
308*5f39d1b3SJooyung Han         "test %[start_depth], %[start_depth] \n\t"
309*5f39d1b3SJooyung Han         "jz storeDst%= \n\t"
310*5f39d1b3SJooyung Han 
311*5f39d1b3SJooyung Han         "vpaddd 0x00(%[dst_ptr]), %%ymm4, %%ymm4 \n\t"    // rhs0
312*5f39d1b3SJooyung Han         "vpaddd 0x20(%[dst_ptr]), %%ymm8, %%ymm8 \n\t"    // rhs0
313*5f39d1b3SJooyung Han         "vpaddd 0x40(%[dst_ptr]), %%ymm12, %%ymm12 \n\t"  // rhs0
314*5f39d1b3SJooyung Han 
315*5f39d1b3SJooyung Han         "vpaddd 0x00(%[dst_ptr], %%r12, 1) , %%ymm5, %%ymm5   \n\t"  // rhs1
316*5f39d1b3SJooyung Han         "vpaddd 0x20(%[dst_ptr], %%r12, 1) , %%ymm9, %%ymm9   \n\t"  // rhs1
317*5f39d1b3SJooyung Han         "vpaddd 0x40(%[dst_ptr], %%r12, 1) , %%ymm13, %%ymm13 \n\t"  // rhs1
318*5f39d1b3SJooyung Han 
319*5f39d1b3SJooyung Han         "vpaddd 0x00(%[dst_ptr], %%r12, 2) , %%ymm6, %%ymm6   \n\t"  // rhs2
320*5f39d1b3SJooyung Han         "vpaddd 0x20(%[dst_ptr], %%r12, 2) , %%ymm10, %%ymm10 \n\t"  // rhs2
321*5f39d1b3SJooyung Han         "vpaddd 0x40(%[dst_ptr], %%r12, 2) , %%ymm14, %%ymm14 \n\t"  // rhs2
322*5f39d1b3SJooyung Han 
323*5f39d1b3SJooyung Han         "vpaddd 0x00(%[dst_ptr], %%r13, 1) , %%ymm7, %%ymm7   \n\t"  // rhs3
324*5f39d1b3SJooyung Han         "vpaddd 0x20(%[dst_ptr], %%r13, 1) , %%ymm11, %%ymm11 \n\t"  // rhs3
325*5f39d1b3SJooyung Han         "vpaddd 0x40(%[dst_ptr], %%r13, 1) , %%ymm15, %%ymm15 \n\t"  // rhs3
326*5f39d1b3SJooyung Han 
327*5f39d1b3SJooyung Han         "storeDst%=:\n\t"
328*5f39d1b3SJooyung Han 
329*5f39d1b3SJooyung Han         "vmovdqu %%ymm4, 0x00(%[dst_ptr])            \n\t"  // rhs0
330*5f39d1b3SJooyung Han         "vmovdqu %%ymm8, 0x20(%[dst_ptr])            \n\t"  // rhs0
331*5f39d1b3SJooyung Han         "vmovdqu %%ymm12, 0x40(%[dst_ptr])           \n\t"  // rhs0
332*5f39d1b3SJooyung Han 
333*5f39d1b3SJooyung Han         "vmovdqu %%ymm5, 0x00(%[dst_ptr], %%r12, 1)  \n\t"  // rhs1
334*5f39d1b3SJooyung Han         "vmovdqu %%ymm9, 0x20(%[dst_ptr], %%r12, 1)  \n\t"  // rhs1
335*5f39d1b3SJooyung Han         "vmovdqu %%ymm13, 0x40(%[dst_ptr], %%r12, 1) \n\t"  // rhs1
336*5f39d1b3SJooyung Han 
337*5f39d1b3SJooyung Han         "vmovdqu %%ymm6, 0x00(%[dst_ptr], %%r12, 2)  \n\t"  // rhs2
338*5f39d1b3SJooyung Han         "vmovdqu %%ymm10, 0x20(%[dst_ptr], %%r12, 2) \n\t"  // rhs2
339*5f39d1b3SJooyung Han         "vmovdqu %%ymm14, 0x40(%[dst_ptr], %%r12, 2) \n\t"  // rhs2
340*5f39d1b3SJooyung Han 
341*5f39d1b3SJooyung Han         "vmovdqu %%ymm7, 0x00(%[dst_ptr], %%r13, 1)  \n\t"  // rhs3
342*5f39d1b3SJooyung Han         "vmovdqu %%ymm11, 0x20(%[dst_ptr], %%r13, 1) \n\t"  // rhs3
343*5f39d1b3SJooyung Han         "vmovdqu %%ymm15, 0x40(%[dst_ptr], %%r13, 1) \n\t"  // rhs3
344*5f39d1b3SJooyung Han 
345*5f39d1b3SJooyung Han         :  // outputs
346*5f39d1b3SJooyung Han         [lhs_ptr] "+r"(lhs_ptr), [rhs_ptr] "+r"(rhs_ptr),
347*5f39d1b3SJooyung Han         [dst_ptr] "+r"(dst_ptr)
348*5f39d1b3SJooyung Han         :  // inputs
349*5f39d1b3SJooyung Han         [start_depth] "r"(start_depth), [dst_col_stride_q] "r"(dst_col_stride_q),
350*5f39d1b3SJooyung Han         [run_depth_cells] "r"(run_depth_cells)
351*5f39d1b3SJooyung Han         :  // clobbers
352*5f39d1b3SJooyung Han         "cc", "memory", "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7",
353*5f39d1b3SJooyung Han         "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15", "%r12",
354*5f39d1b3SJooyung Han         "%r13", "%r14");
355*5f39d1b3SJooyung Han   }
356*5f39d1b3SJooyung Han };
357*5f39d1b3SJooyung Han #endif
358*5f39d1b3SJooyung Han 
359*5f39d1b3SJooyung Han }  // namespace gemmlowp
360*5f39d1b3SJooyung Han 
361*5f39d1b3SJooyung Han #endif  // GEMMLOWP_INTERNAL_KERNEL_AVX_H_
362