From 86f4264c7cd7deb425ea998566f4eaec0dcd86bc Mon Sep 17 00:00:00 2001 From: nihuini Date: Thu, 7 Jun 2018 11:26:06 +0800 Subject: [PATCH] arm neon assembly for winograd5 --- src/layer/arm/convolution_3x3.h | 3605 +++++++++++++++++++++---------- 1 file changed, 2489 insertions(+), 1116 deletions(-) diff --git a/src/layer/arm/convolution_3x3.h b/src/layer/arm/convolution_3x3.h index 0e9b47856..36075e098 100644 --- a/src/layer/arm/convolution_3x3.h +++ b/src/layer/arm/convolution_3x3.h @@ -1588,10 +1588,14 @@ static void conv3x3s1_winograd64_transform_kernel_neon5(const Mat& kernel, Mat& // interleave weights // Mat kernel_tm2(8*8, inch, outch); // Mat kernel_tm2(inch, 64, outch); -// Mat kernel_tm2(4*4*(inch/4), 64, outch/4); +#if __aarch64__ Mat kernel_tm2(8*4*(inch/4) + 8*(inch%4), 64, outch/8 + (outch%8)/4 + outch%4); +#else + Mat kernel_tm2(4*4*(inch/4) + 4*(inch%4), 64, outch/4 + outch%4); +#endif int p=0; +#if __aarch64__ for (; p+7> 3; + remain_outch_start = nn_outch << 3; + + #pragma omp parallel for + for (int pp=0; pp> 2 + "cmp w4, #0 \n" + "beq 1f \n" + + "0: \n" + + "prfm pldl1keep, [%8, #512] \n" + "ld1 {v8.4s, v9.4s, v10.4s, v11.4s}, [%8], #64 \n" + + "prfm pldl1keep, [%9, #512] \n" + "ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [%9], #64 \n" + + "fmla v16.4s, v8.4s, v0.s[0] \n" + "fmla v17.4s, v9.4s, v0.s[0] \n" + "fmla v18.4s, v8.4s, v1.s[0] \n" + "fmla v19.4s, v9.4s, v1.s[0] \n" + + "prfm pldl1keep, [%9, #512] \n" + "ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [%9], #64 \n" + + "fmla v20.4s, v8.4s, v2.s[0] \n" + "fmla v21.4s, v9.4s, v2.s[0] \n" + "fmla v22.4s, v8.4s, v3.s[0] \n" + "fmla v23.4s, v9.4s, v3.s[0] \n" + + "fmla v24.4s, v8.4s, v4.s[0] \n" + "fmla v25.4s, v9.4s, v4.s[0] \n" + "fmla v26.4s, v8.4s, v5.s[0] \n" + "fmla v27.4s, v9.4s, v5.s[0] \n" + "fmla v28.4s, v8.4s, v6.s[0] \n" + "fmla v29.4s, v9.4s, v6.s[0] \n" + "fmla v30.4s, v8.4s, v7.s[0] \n" + "fmla v31.4s, v9.4s, v7.s[0] \n" + + "fmla v16.4s, v10.4s, v0.s[1] \n" + "fmla v17.4s, v11.4s, v0.s[1] \n" + "fmla v18.4s, v10.4s, v1.s[1] \n" + "fmla v19.4s, v11.4s, v1.s[1] \n" + "fmla v20.4s, v10.4s, v2.s[1] \n" + "fmla v21.4s, v11.4s, v2.s[1] \n" + "fmla v22.4s, v10.4s, v3.s[1] \n" + "fmla v23.4s, v11.4s, v3.s[1] \n" + + "prfm pldl1keep, [%8, #512] \n" + "ld1 {v12.4s, v13.4s, v14.4s, v15.4s}, [%8], #64 \n" + + "fmla v24.4s, v10.4s, v4.s[1] \n" + "fmla v25.4s, v11.4s, v4.s[1] \n" + "fmla v26.4s, v10.4s, v5.s[1] \n" + "fmla v27.4s, v11.4s, v5.s[1] \n" + "fmla v28.4s, v10.4s, v6.s[1] \n" + "fmla v29.4s, v11.4s, v6.s[1] \n" + "fmla v30.4s, v10.4s, v7.s[1] \n" + "fmla v31.4s, v11.4s, v7.s[1] \n" + + "fmla v16.4s, v12.4s, v0.s[2] \n" + "fmla v17.4s, v13.4s, v0.s[2] \n" + "fmla v18.4s, v12.4s, v1.s[2] \n" + "fmla v19.4s, v13.4s, v1.s[2] \n" + "fmla v20.4s, v12.4s, v2.s[2] \n" + "fmla v21.4s, v13.4s, v2.s[2] \n" + "fmla v22.4s, v12.4s, v3.s[2] \n" + "fmla v23.4s, v13.4s, v3.s[2] \n" + + "fmla v24.4s, v12.4s, v4.s[2] \n" + "fmla v25.4s, v13.4s, v4.s[2] \n" + "fmla v26.4s, v12.4s, v5.s[2] \n" + "fmla v27.4s, v13.4s, v5.s[2] \n" + "fmla v28.4s, v12.4s, v6.s[2] \n" + "fmla v29.4s, v13.4s, v6.s[2] \n" + "fmla v30.4s, v12.4s, v7.s[2] \n" + "fmla v31.4s, v13.4s, v7.s[2] \n" + + "fmla v16.4s, v14.4s, v0.s[3] \n" + "fmla v17.4s, v15.4s, v0.s[3] \n" + "fmla v18.4s, v14.4s, v1.s[3] \n" + "fmla v19.4s, v15.4s, v1.s[3] \n" + "fmla v20.4s, v14.4s, v2.s[3] \n" + "fmla v21.4s, v15.4s, v2.s[3] \n" + "fmla v22.4s, v14.4s, v3.s[3] \n" + "fmla v23.4s, v15.4s, v3.s[3] \n" + + "subs w4, w4, #1 \n" + + "fmla v24.4s, v14.4s, v4.s[3] \n" + "fmla v25.4s, v15.4s, v4.s[3] \n" + "fmla v26.4s, v14.4s, v5.s[3] \n" + "fmla v27.4s, v15.4s, v5.s[3] \n" + "fmla v28.4s, v14.4s, v6.s[3] \n" + "fmla v29.4s, v15.4s, v6.s[3] \n" + "fmla v30.4s, v14.4s, v7.s[3] \n" + "fmla v31.4s, v15.4s, v7.s[3] \n" + + "bne 0b \n" + + "1: \n" + + // remain loop + "and w4, %w20, #3 \n"// w4 = remain = tiles & 3; + "cmp w4, #0 \n" + "beq 3f \n" + + "2: \n" + + "prfm pldl1keep, [%8, #256] \n" + "ld1 {v8.4s, v9.4s}, [%8], #32 \n" + + "prfm pldl1keep, [%9, #256] \n" + "ld1 {v0.4s, v1.4s}, [%9], #32 \n" + + "fmla v16.4s, v8.4s, v0.s[0] \n" + "fmla v17.4s, v9.4s, v0.s[0] \n" + "fmla v18.4s, v8.4s, v0.s[1] \n" + "fmla v19.4s, v9.4s, v0.s[1] \n" + "fmla v20.4s, v8.4s, v0.s[2] \n" + "fmla v21.4s, v9.4s, v0.s[2] \n" + "fmla v22.4s, v8.4s, v0.s[3] \n" + "fmla v23.4s, v9.4s, v0.s[3] \n" + + "subs w4, w4, #1 \n" + + "fmla v24.4s, v8.4s, v1.s[0] \n" + "fmla v25.4s, v9.4s, v1.s[0] \n" + "fmla v26.4s, v8.4s, v1.s[1] \n" + "fmla v27.4s, v9.4s, v1.s[1] \n" + "fmla v28.4s, v8.4s, v1.s[2] \n" + "fmla v29.4s, v9.4s, v1.s[2] \n" + "fmla v30.4s, v8.4s, v1.s[3] \n" + "fmla v31.4s, v9.4s, v1.s[3] \n" + + "bne 2b \n" + + "3: \n" + + "st1 {v16.4s, v17.4s}, [%0], #32 \n" + "st1 {v18.4s, v19.4s}, [%1], #32 \n" + "st1 {v20.4s, v21.4s}, [%2], #32 \n" + "st1 {v22.4s, v23.4s}, [%3], #32 \n" + "st1 {v24.4s, v25.4s}, [%4], #32 \n" + "st1 {v26.4s, v27.4s}, [%5], #32 \n" + "st1 {v28.4s, v29.4s}, [%6], #32 \n" + "st1 {v30.4s, v31.4s}, [%7], #32 \n" + + : "=r"(output0_tm), // %0 + "=r"(output1_tm), // %1 + "=r"(output2_tm), // %2 + "=r"(output3_tm), // %3 + "=r"(output4_tm), // %4 + "=r"(output5_tm), // %5 + "=r"(output6_tm), // %6 + "=r"(output7_tm), // %7 + "=r"(bb2p0), // %8 + "=r"(ktm0) // %9 + : "0"(output0_tm), + "1"(output1_tm), + "2"(output2_tm), + "3"(output3_tm), + "4"(output4_tm), + "5"(output5_tm), + "6"(output6_tm), + "7"(output7_tm), + "8"(bb2p0), + "9"(ktm0), + "r"(inch) // %20 + : "cc", "memory", "x4", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" + ); + } + for (; i+3> 2 + "cmp w4, #0 \n" + "beq 1f \n" + + "0: \n" + + "prfm pldl1keep, [%8, #512] \n" + "ld1 {v8.4s, v9.4s, v10.4s, v11.4s}, [%8], #64 \n" + + "prfm pldl1keep, [%9, #512] \n" + "ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [%9], #64 \n" + + "fmla v16.4s, v8.4s, v0.s[0] \n" + "fmla v17.4s, v8.4s, v1.s[0] \n" + "fmla v18.4s, v8.4s, v2.s[0] \n" + "fmla v19.4s, v8.4s, v3.s[0] \n" + + "prfm pldl1keep, [%9, #512] \n" + "ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [%9], #64 \n" + + "fmla v20.4s, v8.4s, v4.s[0] \n" + "fmla v21.4s, v8.4s, v5.s[0] \n" + "fmla v22.4s, v8.4s, v6.s[0] \n" + "fmla v23.4s, v8.4s, v7.s[0] \n" + + "fmla v16.4s, v9.4s, v0.s[1] \n" + "fmla v17.4s, v9.4s, v1.s[1] \n" + "fmla v18.4s, v9.4s, v2.s[1] \n" + "fmla v19.4s, v9.4s, v3.s[1] \n" + "fmla v20.4s, v9.4s, v4.s[1] \n" + "fmla v21.4s, v9.4s, v5.s[1] \n" + "fmla v22.4s, v9.4s, v6.s[1] \n" + "fmla v23.4s, v9.4s, v7.s[1] \n" + + "fmla v16.4s, v10.4s, v0.s[2] \n" + "fmla v17.4s, v10.4s, v1.s[2] \n" + "fmla v18.4s, v10.4s, v2.s[2] \n" + "fmla v19.4s, v10.4s, v3.s[2] \n" + "fmla v20.4s, v10.4s, v4.s[2] \n" + "fmla v21.4s, v10.4s, v5.s[2] \n" + "fmla v22.4s, v10.4s, v6.s[2] \n" + "fmla v23.4s, v10.4s, v7.s[2] \n" + + "subs w4, w4, #1 \n" + + "fmla v16.4s, v11.4s, v0.s[3] \n" + "fmla v17.4s, v11.4s, v1.s[3] \n" + "fmla v18.4s, v11.4s, v2.s[3] \n" + "fmla v19.4s, v11.4s, v3.s[3] \n" + "fmla v20.4s, v11.4s, v4.s[3] \n" + "fmla v21.4s, v11.4s, v5.s[3] \n" + "fmla v22.4s, v11.4s, v6.s[3] \n" + "fmla v23.4s, v11.4s, v7.s[3] \n" + + "bne 0b \n" + + "1: \n" + + // remain loop + "and w4, %w20, #3 \n"// w4 = remain = tiles & 3; + "cmp w4, #0 \n" + "beq 3f \n" + + "2: \n" + + "prfm pldl1keep, [%8, #128] \n" + "ld1 {v8.4s}, [%8], #16 \n" + + "prfm pldl1keep, [%9, #256] \n" + "ld1 {v0.4s, v1.4s}, [%9], #32 \n" + + "fmla v16.4s, v8.4s, v0.s[0] \n" + "fmla v17.4s, v8.4s, v0.s[1] \n" + "fmla v18.4s, v8.4s, v0.s[2] \n" + "fmla v19.4s, v8.4s, v0.s[3] \n" + + "subs w4, w4, #1 \n" + + "fmla v20.4s, v8.4s, v1.s[0] \n" + "fmla v21.4s, v8.4s, v1.s[1] \n" + "fmla v22.4s, v8.4s, v1.s[2] \n" + "fmla v23.4s, v8.4s, v1.s[3] \n" + + "bne 2b \n" + + "3: \n" + + "st1 {v16.4s}, [%0], #16 \n" + "st1 {v17.4s}, [%1], #16 \n" + "st1 {v18.4s}, [%2], #16 \n" + "st1 {v19.4s}, [%3], #16 \n" + "st1 {v20.4s}, [%4], #16 \n" + "st1 {v21.4s}, [%5], #16 \n" + "st1 {v22.4s}, [%6], #16 \n" + "st1 {v23.4s}, [%7], #16 \n" + + : "=r"(output0_tm), // %0 + "=r"(output1_tm), // %1 + "=r"(output2_tm), // %2 + "=r"(output3_tm), // %3 + "=r"(output4_tm), // %4 + "=r"(output5_tm), // %5 + "=r"(output6_tm), // %6 + "=r"(output7_tm), // %7 + "=r"(bb2p0), // %8 + "=r"(ktm0) // %9 + : "0"(output0_tm), + "1"(output1_tm), + "2"(output2_tm), + "3"(output3_tm), + "4"(output4_tm), + "5"(output5_tm), + "6"(output6_tm), + "7"(output7_tm), + "8"(bb2p0), + "9"(ktm0), + "r"(inch) // %20 + : "cc", "memory", "x4", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23" + ); + } + for (; i> 2; + + #pragma omp parallel for + for (int pp=0; pp> 2 + "cmp w4, #0 \n" + "beq 1f \n" + + "0: \n" + + "prfm pldl1keep, [%4, #512] \n" + "ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [%4], #64 \n" + + "prfm pldl1keep, [%5, #512] \n" + "ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [%5], #64 \n" + + "fmla v8.4s, v4.4s, v0.s[0] \n" + "fmla v9.4s, v5.4s, v0.s[0] \n" + "fmla v10.4s, v4.4s, v1.s[0] \n" + "fmla v11.4s, v5.4s, v1.s[0] \n" + "fmla v12.4s, v4.4s, v2.s[0] \n" + "fmla v13.4s, v5.4s, v2.s[0] \n" + "fmla v14.4s, v4.4s, v3.s[0] \n" + "fmla v15.4s, v5.4s, v3.s[0] \n" + + "fmla v8.4s, v6.4s, v0.s[1] \n" + "fmla v9.4s, v7.4s, v0.s[1] \n" + "fmla v10.4s, v6.4s, v1.s[1] \n" + "fmla v11.4s, v7.4s, v1.s[1] \n" + "fmla v12.4s, v6.4s, v2.s[1] \n" + "fmla v13.4s, v7.4s, v2.s[1] \n" + "fmla v14.4s, v6.4s, v3.s[1] \n" + "fmla v15.4s, v7.4s, v3.s[1] \n" + + "prfm pldl1keep, [%4, #512] \n" + "ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%4], #64 \n" + + "fmla v8.4s, v16.4s, v0.s[2] \n" + "fmla v9.4s, v17.4s, v0.s[2] \n" + "fmla v10.4s, v16.4s, v1.s[2] \n" + "fmla v11.4s, v17.4s, v1.s[2] \n" + "fmla v12.4s, v16.4s, v2.s[2] \n" + "fmla v13.4s, v17.4s, v2.s[2] \n" + "fmla v14.4s, v16.4s, v3.s[2] \n" + "fmla v15.4s, v17.4s, v3.s[2] \n" + + "fmla v8.4s, v18.4s, v0.s[3] \n" + "fmla v9.4s, v19.4s, v0.s[3] \n" + "fmla v10.4s, v18.4s, v1.s[3] \n" + "fmla v11.4s, v19.4s, v1.s[3] \n" + "fmla v12.4s, v18.4s, v2.s[3] \n" + "fmla v13.4s, v19.4s, v2.s[3] \n" + "fmla v14.4s, v18.4s, v3.s[3] \n" + "fmla v15.4s, v19.4s, v3.s[3] \n" + + "subs w4, w4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and w4, %w12, #3 \n"// w4 = remain = tiles & 3; + "cmp w4, #0 \n" + "beq 3f \n" + + "2: \n" + + "prfm pldl1keep, [%4, #256] \n" + "ld1 {v4.4s, v5.4s}, [%4], #32 \n" + + "prfm pldl1keep, [%5, #128] \n" + "ld1 {v0.4s}, [%5], #16 \n" + + "fmla v8.4s, v4.4s, v0.s[0] \n" + "fmla v9.4s, v5.4s, v0.s[0] \n" + "fmla v10.4s, v4.4s, v0.s[1] \n" + "fmla v11.4s, v5.4s, v0.s[1] \n" + "fmla v12.4s, v4.4s, v0.s[2] \n" + "fmla v13.4s, v5.4s, v0.s[2] \n" + "fmla v14.4s, v4.4s, v0.s[3] \n" + "fmla v15.4s, v5.4s, v0.s[3] \n" + + "subs w4, w4, #1 \n" + "bne 2b \n" + + "3: \n" + + "st1 {v8.4s, v9.4s}, [%0], #32 \n" + "st1 {v10.4s, v11.4s}, [%1], #32 \n" + "st1 {v12.4s, v13.4s}, [%2], #32 \n" + "st1 {v14.4s, v15.4s}, [%3], #32 \n" + + : "=r"(output0_tm), // %0 + "=r"(output1_tm), // %1 + "=r"(output2_tm), // %2 + "=r"(output3_tm), // %3 + "=r"(bb2p0), // %4 + "=r"(ktm0) // %5 + : "0"(output0_tm), + "1"(output1_tm), + "2"(output2_tm), + "3"(output3_tm), + "4"(bb2p0), + "5"(ktm0), + "r"(inch) // %12 + : "cc", "memory", "x4", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19" + ); +#else // __aarch64__ + asm volatile( + "veor q8, q8, q8 \n" + "veor q9, q9, q9 \n" + "veor q10, q10, q10 \n" + "veor q11, q11, q11 \n" + "veor q12, q12, q12 \n" + "veor q13, q13, q13 \n" + "veor q14, q14, q14 \n" + "veor q15, q15, q15 \n" + + // inch loop + "lsr r4, %12, #2 \n"// r4 = nn = inch >> 2 + "cmp r4, #0 \n" + "beq 1f \n" + + "0: \n" + + "pld [%4, #512] \n" +// "vldm %4!, {d8-d15} \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + "vld1.f32 {d12-d15}, [%4 :128]! \n" + + "pld [%5, #512] \n" +// "vldm %5!, {d0-d7} \n" + "vld1.f32 {d0-d3}, [%5 :128]! \n" + "vld1.f32 {d4-d7}, [%5 :128]! \n" + + "vmla.f32 q8, q4, d0[0] \n" + "vmla.f32 q9, q5, d0[0] \n" + "vmla.f32 q10, q4, d2[0] \n" + "vmla.f32 q11, q5, d2[0] \n" + "vmla.f32 q12, q4, d4[0] \n" + "vmla.f32 q13, q5, d4[0] \n" + "vmla.f32 q14, q4, d6[0] \n" + "vmla.f32 q15, q5, d6[0] \n" + + "vmla.f32 q8, q6, d0[1] \n" + "vmla.f32 q9, q7, d0[1] \n" + "vmla.f32 q10, q6, d2[1] \n" + "vmla.f32 q11, q7, d2[1] \n" + "vmla.f32 q12, q6, d4[1] \n" + "vmla.f32 q13, q7, d4[1] \n" + "vmla.f32 q14, q6, d6[1] \n" + "vmla.f32 q15, q7, d6[1] \n" + + "pld [%4, #512] \n" +// "vldm %4!, {d8-d15} \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + "vld1.f32 {d12-d15}, [%4 :128]! \n" + + "vmla.f32 q8, q4, d1[0] \n" + "vmla.f32 q9, q5, d1[0] \n" + "vmla.f32 q10, q4, d3[0] \n" + "vmla.f32 q11, q5, d3[0] \n" + "vmla.f32 q12, q4, d5[0] \n" + "vmla.f32 q13, q5, d5[0] \n" + "vmla.f32 q14, q4, d7[0] \n" + "vmla.f32 q15, q5, d7[0] \n" + + "vmla.f32 q8, q6, d1[1] \n" + "vmla.f32 q9, q7, d1[1] \n" + "vmla.f32 q10, q6, d3[1] \n" + "vmla.f32 q11, q7, d3[1] \n" + "vmla.f32 q12, q6, d5[1] \n" + "vmla.f32 q13, q7, d5[1] \n" + "vmla.f32 q14, q6, d7[1] \n" + "vmla.f32 q15, q7, d7[1] \n" + + "subs r4, r4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and r4, %12, #3 \n"// r4 = remain = tiles & 3; + "cmp r4, #0 \n" + "beq 3f \n" + + "2: \n" + + "pld [%4, #256] \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + + "pld [%5, #128] \n" + "vld1.f32 {d0-d1}, [%5 :128]! \n" + + "vmla.f32 q8, q4, d0[0] \n" + "vmla.f32 q9, q5, d0[0] \n" + "vmla.f32 q10, q4, d0[1] \n" + "vmla.f32 q11, q5, d0[1] \n" + "vmla.f32 q12, q4, d1[0] \n" + "vmla.f32 q13, q5, d1[0] \n" + "vmla.f32 q14, q4, d1[1] \n" + "vmla.f32 q15, q5, d1[1] \n" + + "subs r4, r4, #1 \n" + "bne 2b \n" + + "3: \n" + + "vst1.f32 {d16-d19}, [%0]! \n" + "vst1.f32 {d20-d23}, [%1]! \n" + "vst1.f32 {d24-d27}, [%2]! \n" + "vst1.f32 {d28-d31}, [%3]! \n" + + : "=r"(output0_tm), // %0 + "=r"(output1_tm), // %1 + "=r"(output2_tm), // %2 + "=r"(output3_tm), // %3 + "=r"(bb2p0), // %4 + "=r"(ktm0) // %5 + : "0"(output0_tm), + "1"(output1_tm), + "2"(output2_tm), + "3"(output3_tm), + "4"(bb2p0), + "5"(ktm0), + "r"(inch) // %12 + : "cc", "memory", "r4", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); +#endif // __aarch64__ + } + for (; i+3> 2 + "cmp w4, #0 \n" + "beq 1f \n" + + "0: \n" + + "prfm pldl1keep, [%4, #512] \n" + "ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [%4], #64 \n" + + "prfm pldl1keep, [%5, #512] \n" + "ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [%5], #64 \n" + + "fmla v8.4s, v4.4s, v0.s[0] \n" + "fmla v9.4s, v4.4s, v1.s[0] \n" + "fmla v10.4s, v4.4s, v2.s[0] \n" + "fmla v11.4s, v4.4s, v3.s[0] \n" + + "fmla v8.4s, v5.4s, v0.s[1] \n" + "fmla v9.4s, v5.4s, v1.s[1] \n" + "fmla v10.4s, v5.4s, v2.s[1] \n" + "fmla v11.4s, v5.4s, v3.s[1] \n" + + "fmla v8.4s, v6.4s, v0.s[2] \n" + "fmla v9.4s, v6.4s, v1.s[2] \n" + "fmla v10.4s, v6.4s, v2.s[2] \n" + "fmla v11.4s, v6.4s, v3.s[2] \n" + + "fmla v8.4s, v7.4s, v0.s[3] \n" + "fmla v9.4s, v7.4s, v1.s[3] \n" + "fmla v10.4s, v7.4s, v2.s[3] \n" + "fmla v11.4s, v7.4s, v3.s[3] \n" + + "subs w4, w4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and w4, %w12, #3 \n"// w4 = remain = tiles & 3; + "cmp w4, #0 \n" + "beq 3f \n" + + "2: \n" + + "prfm pldl1keep, [%4, #128] \n" + "ld1 {v4.4s}, [%4], #16 \n" + + "prfm pldl1keep, [%5, #128] \n" + "ld1 {v0.4s}, [%5], #16 \n" + + "fmla v8.4s, v4.4s, v0.s[0] \n" + "fmla v9.4s, v4.4s, v0.s[1] \n" + "fmla v10.4s, v4.4s, v0.s[2] \n" + "fmla v11.4s, v4.4s, v0.s[3] \n" + + "subs w4, w4, #1 \n" + "bne 2b \n" + + "3: \n" + + "st1 {v8.4s}, [%0], #16 \n" + "st1 {v9.4s}, [%1], #16 \n" + "st1 {v10.4s}, [%2], #16 \n" + "st1 {v11.4s}, [%3], #16 \n" + + : "=r"(output0_tm), // %0 + "=r"(output1_tm), // %1 + "=r"(output2_tm), // %2 + "=r"(output3_tm), // %3 + "=r"(bb2p0), // %4 + "=r"(ktm0) // %5 + : "0"(output0_tm), + "1"(output1_tm), + "2"(output2_tm), + "3"(output3_tm), + "4"(bb2p0), + "5"(ktm0), + "r"(inch) // %12 + : "cc", "memory", "x4", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11" + ); +#else // __aarch64__ + asm volatile( + "veor q8, q8, q8 \n" + "veor q9, q9, q9 \n" + "veor q10, q10, q10 \n" + "veor q11, q11, q11 \n" + + // inch loop + "lsr r4, %12, #2 \n"// r4 = nn = inch >> 2 + "cmp r4, #0 \n" + "beq 1f \n" + + "0: \n" + + "pld [%4, #512] \n" +// "vldm %4!, {d8-d15} \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + "vld1.f32 {d12-d15}, [%4 :128]! \n" + + "pld [%5, #512] \n" +// "vldm %5!, {d0-d7} \n" + "vld1.f32 {d0-d3}, [%5 :128]! \n" + "vld1.f32 {d4-d7}, [%5 :128]! \n" + + "vmla.f32 q8, q4, d0[0] \n" + "vmla.f32 q9, q4, d2[0] \n" + "vmla.f32 q10, q4, d4[0] \n" + "vmla.f32 q11, q4, d6[0] \n" + + "vmla.f32 q8, q5, d0[1] \n" + "vmla.f32 q9, q5, d2[1] \n" + "vmla.f32 q10, q5, d4[1] \n" + "vmla.f32 q11, q5, d6[1] \n" + + "vmla.f32 q8, q6, d1[0] \n" + "vmla.f32 q9, q6, d3[0] \n" + "vmla.f32 q10, q6, d5[0] \n" + "vmla.f32 q11, q6, d7[0] \n" + + "vmla.f32 q8, q7, d1[1] \n" + "vmla.f32 q9, q7, d3[1] \n" + "vmla.f32 q10, q7, d5[1] \n" + "vmla.f32 q11, q7, d7[1] \n" + + "subs r4, r4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and r4, %12, #3 \n"// r4 = remain = tiles & 3; + "cmp r4, #0 \n" + "beq 3f \n" + + "2: \n" + + "pld [%4, #128] \n" + "vld1.f32 {d8-d9}, [%4 :128]! \n" + + "pld [%5, #128] \n" + "vld1.f32 {d0-d1}, [%5 :128]! \n" + + "vmla.f32 q8, q4, d0[0] \n" + "vmla.f32 q9, q4, d0[1] \n" + "vmla.f32 q10, q4, d1[0] \n" + "vmla.f32 q11, q4, d1[1] \n" + + "subs r4, r4, #1 \n" + "bne 2b \n" + + "3: \n" + + "vst1.f32 {d16-d17}, [%0]! \n" + "vst1.f32 {d18-d19}, [%1]! \n" + "vst1.f32 {d20-d21}, [%2]! \n" + "vst1.f32 {d22-d23}, [%3]! \n" + + : "=r"(output0_tm), // %0 + "=r"(output1_tm), // %1 + "=r"(output2_tm), // %2 + "=r"(output3_tm), // %3 + "=r"(bb2p0), // %4 + "=r"(ktm0) // %5 + : "0"(output0_tm), + "1"(output1_tm), + "2"(output2_tm), + "3"(output3_tm), + "4"(bb2p0), + "5"(ktm0), + "r"(inch) // %12 + : "cc", "memory", "r4", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11" + ); +#endif // __aarch64__ + } + for (; i> 2 + "cmp w4, #0 \n" + "beq 1f \n" + + "0: \n" + + "prfm pldl1keep, [%4, #512] \n" + "ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [%4], #64 \n" + + "prfm pldl1keep, [%5, #128] \n" + "ld1 {v0.4s}, [%5], #16 \n" + + "fmla v8.4s, v4.4s, v0.s[0] \n" + "fmla v9.4s, v5.4s, v0.s[0] \n" + "fmla v8.4s, v6.4s, v0.s[1] \n" + "fmla v9.4s, v7.4s, v0.s[1] \n" + + "prfm pldl1keep, [%4, #512] \n" + "ld1 {v12.4s, v13.4s, v14.4s, v15.4s}, [%4], #64 \n" + + "fmla v8.4s, v12.4s, v0.s[2] \n" + "fmla v9.4s, v13.4s, v0.s[2] \n" + "fmla v8.4s, v14.4s, v0.s[3] \n" + "fmla v9.4s, v15.4s, v0.s[3] \n" + + "subs w4, w4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and w4, %w6, #3 \n"// w4 = remain = tiles & 3; + "cmp w4, #0 \n" + "beq 3f \n" + + "2: \n" + + "prfm pldl1keep, [%4, #256] \n" + "ld1 {v4.4s, v5.4s}, [%4], #32 \n" + + "prfm pldl1keep, [%5, #32] \n" + "ld1r {v0.4s}, [%5], #4 \n" + + "fmla v8.4s, v4.4s, v0.4s \n" + "fmla v9.4s, v5.4s, v0.4s \n" + + "subs w4, w4, #1 \n" + "bne 2b \n" + + "3: \n" + + "st1 {v8.4s, v9.4s}, [%0], #32 \n" + + : "=r"(output0_tm), // %0 + "=r"(bb2p0), // %1 + "=r"(ktm0) // %2 + : "0"(output0_tm), + "1"(bb2p0), + "2"(ktm0), + "r"(inch) // %6 + : "cc", "memory", "x4", "v0", "v4", "v5", "v6", "v7", "v8", "v9", "v12", "v13", "v14", "v15" + ); +#else // __aarch64__ + asm volatile( + "veor q8, q8, q8 \n" + "veor q9, q9, q9 \n" + + // inch loop + "lsr r4, %6, #2 \n"// r4 = nn = inch >> 2 + "cmp r4, #0 \n" + "beq 1f \n" + + "0: \n" + + "pld [%4, #512] \n" +// "vldm %4!, {d8-d15} \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + "vld1.f32 {d12-d15}, [%4 :128]! \n" + + "pld [%5, #128] \n" + "vld1.f32 {d0-d1}, [%5 :128]! \n" + + "vmla.f32 q8, q4, d0[0] \n" + "vmla.f32 q9, q5, d0[0] \n" + "vmla.f32 q8, q6, d0[1] \n" + "vmla.f32 q9, q7, d0[1] \n" + + "pld [%4, #512] \n" +// "vldm %4!, {d24-d31} \n" + "vld1.f32 {d24-d27}, [%4 :128]! \n" + "vld1.f32 {d28-d31}, [%4 :128]! \n" + + "vmla.f32 q8, q12, d1[0] \n" + "vmla.f32 q9, q13, d1[0] \n" + "vmla.f32 q8, q14, d1[1] \n" + "vmla.f32 q9, q15, d1[1] \n" + + "subs r4, r4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and r4, %6, #3 \n"// r4 = remain = tiles & 3; + "cmp r4, #0 \n" + "beq 3f \n" + + "2: \n" + + "pld [%4, #256] \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + + "pld [%5, #32] \n" + "vld1.f32 {d0[],d1[]}, [%5]! \n" + + "vmla.f32 q8, q4, q0 \n" + "vmla.f32 q9, q5, q0 \n" + + "subs r4, r4, #1 \n" + "bne 2b \n" + + "3: \n" + + "vst1.f32 {d16-d19}, [%0]! \n" + + : "=r"(output0_tm), // %0 + "=r"(bb2p0), // %1 + "=r"(ktm0) // %2 + : "0"(output0_tm), + "1"(bb2p0), + "2"(ktm0), + "r"(inch) // %6 + : "cc", "memory", "r4", "q0", "q4", "q5", "q6", "q7", "q8", "q9", "q12", "q13", "q14", "q15" + ); +#endif // __aarch64__ + } + for (; i+3> 2 + "cmp w4, #0 \n" + "beq 1f \n" + + "0: \n" + + "prfm pldl1keep, [%4, #512] \n" + "ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [%4], #64 \n" + + "prfm pldl1keep, [%5, #128] \n" + "ld1 {v0.4s}, [%5], #16 \n" + + "fmla v8.4s, v4.4s, v0.s[0] \n" + "fmla v8.4s, v5.4s, v0.s[1] \n" + "fmla v8.4s, v6.4s, v0.s[2] \n" + "fmla v8.4s, v7.4s, v0.s[3] \n" + + "subs w4, w4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and w4, %w6, #3 \n"// w4 = remain = tiles & 3; + "cmp w4, #0 \n" + "beq 3f \n" + + "2: \n" + + "prfm pldl1keep, [%4, #128] \n" + "ld1 {v4.4s}, [%4], #16 \n" + + "prfm pldl1keep, [%5, #32] \n" + "ld1r {v0.4s}, [%5], #4 \n" + + "fmla v8.4s, v4.4s, v0.4s \n" + + "subs w4, w4, #1 \n" + "bne 2b \n" + + "3: \n" + + "st1 {v8.4s}, [%0], #16 \n" + + : "=r"(output0_tm), // %0 + "=r"(bb2p0), // %1 + "=r"(ktm0) // %2 + : "0"(output0_tm), + "1"(bb2p0), + "2"(ktm0), + "r"(inch) // %6 + : "cc", "memory", "x4", "v0", "v4", "v5", "v6", "v7", "v8" + ); +#else // __aarch64__ + asm volatile( + "veor q8, q8, q8 \n" + + // inch loop + "lsr r4, %6, #2 \n"// r4 = nn = inch >> 2 + "cmp r4, #0 \n" + "beq 1f \n" + + "0: \n" + + "pld [%4, #512] \n" +// "vldm %4!, {d8-d15} \n" + "vld1.f32 {d8-d11}, [%4 :128]! \n" + "vld1.f32 {d12-d15}, [%4 :128]! \n" + + "pld [%5, #128] \n" + "vld1.f32 {d0-d1}, [%5 :128]! \n" + + "vmla.f32 q8, q4, d0[0] \n" + "vmla.f32 q8, q5, d0[1] \n" + "vmla.f32 q8, q6, d1[0] \n" + "vmla.f32 q8, q7, d1[1] \n" + + "subs r4, r4, #1 \n" + "bne 0b \n" + + "1: \n" + + // remain loop + "and r4, %6, #3 \n"// r4 = remain = tiles & 3; + "cmp r4, #0 \n" + "beq 3f \n" + + "2: \n" + + "pld [%4, #128] \n" + "vld1.f32 {d8-d9}, [%4]! \n" + + "pld [%5, #32] \n" + "vld1.f32 {d0[],d1[]}, [%5]! \n" + + "vmla.f32 q8, q4, q0 \n" + + "subs r4, r4, #1 \n" + "bne 2b \n" + + "3: \n" + + "vst1.f32 {d16-d17}, [%0]! \n" + + : "=r"(output0_tm), // %0 + "=r"(bb2p0), // %1 + "=r"(ktm0) // %2 + : "0"(output0_tm), + "1"(bb2p0), + "2"(ktm0), + "r"(inch) // %6 + : "cc", "memory", "r4", "q0", "q4", "q5", "q6", "q7", "q8" + ); +#endif // __aarch64__ + } + for (; i