asm volatile( "0: \n" //ld r0-r7 "pld [%5, #64] \n" "vld1.s8 {d0}, [%5 :64]! \n" //r0 "pld [%6, #64] \n" "vld1.s8 {d1}, [%6 :64]! \n" //r1 "pld [%7, #64] \n" "vld1.s8 {d2}, [%7 :64]! \n" //r2 "pld [%8, #64] \n" "vld1.s8 {d3}, [%8 :64]! \n" //r3 "pld [%9, #64] \n" "vld1.s8 {d4}, [%9 :64]! \n" //r4 "pld [%10, #64] \n" "vld1.s8 {d5}, [%10 :64]! \n" //r5 "pld [%11, #64] \n" "vld1.s8 {d6}, [%11 :64]! \n" //r6 "pld [%12, #64] \n" "vld1.s8 {d7}, [%12 :64]! \n" //r7 //########################################### //load inch kernel_0 k0-k7 "vdup.s8 d8, d18[0] \n" "vdup.s8 d9, d18[1] \n" "vdup.s8 d10, d18[2] \n" "vdup.s8 d11, d18[3] \n" "vdup.s8 d12, d18[4] \n" "vdup.s8 d13, d18[5] \n" "vdup.s8 d14, d18[6] \n" "vdup.s8 d15, d18[7] \n" //mla "vmull.s8 q8, d0, d8 \n" "vmlal.s8 q8, d1, d9 \n" "vmlal.s8 q8, d2, d10 \n" "vmlal.s8 q8, d3, d11 \n" "vmlal.s8 q8, d4, d12 \n" "vmlal.s8 q8, d5, d13 \n" "vmlal.s8 q8, d6, d14 \n" "vmlal.s8 q8, d7, d15 \n" //"pld [%1, #128] \n" "vld1.32 {d20-d23}, [%1:128] \n" // outptr0_s32 "vaddw.s16 q10, q10, d16 \n" "vaddw.s16 q11, q11, d17 \n" "vst1.32 {d20-d23}, [%1:128]!\n" // outptr0_s32 //########################################### //load inch kernel_1 k0-k7 "vdup.s8 d8, d19[0] \n" "vdup.s8 d9, d19[1] \n" "vdup.s8 d10, d19[2] \n" "vdup.s8 d11, d19[3] \n" "vdup.s8 d12, d19[4] \n" "vdup.s8 d13, d19[5] \n" "vdup.s8 d14, d19[6] \n" "vdup.s8 d15, d19[7] \n" //mla "vmull.s8 q8, d0, d8 \n" "vmlal.s8 q8, d1, d9 \n" "vmlal.s8 q8, d2, d10 \n" "vmlal.s8 q8, d3, d11 \n" "vmlal.s8 q8, d4, d12 \n" "vmlal.s8 q8, d5, d13 \n" "vmlal.s8 q8, d6, d14 \n" "vmlal.s8 q8, d7, d15 \n" //"pld [%2, #128] \n" "vld1.32 {d20-d23}, [%2:128] \n" // outptr1_s32 "vaddw.s16 q10, q10, d16 \n" "vaddw.s16 q11, q11, d17 \n" "vst1.32 {d20-d23}, [%2:128]!\n" // outptr1_s32 //############################################ //load inch kernel_2 k0-k7 "vdup.s8 d8, d24[0] \n" "vdup.s8 d9, d24[1] \n" "vdup.s8 d10, d24[2] \n" "vdup.s8 d11, d24[3] \n" "vdup.s8 d12, d24[4] \n" "vdup.s8 d13, d24[5] \n" "vdup.s8 d14, d24[6] \n" "vdup.s8 d15, d24[7] \n" //mla "vmull.s8 q8, d0, d8 \n" "vmlal.s8 q8, d1, d9 \n" "vmlal.s8 q8, d2, d10 \n" "vmlal.s8 q8, d3, d11 \n" "vmlal.s8 q8, d4, d12 \n" "vmlal.s8 q8, d5, d13 \n" "vmlal.s8 q8, d6, d14 \n" "vmlal.s8 q8, d7, d15 \n" //"pld [%3, #128] \n" "vld1.32 {d20-d23}, [%3:128] \n" // outptr2_s32 "vaddw.s16 q10, q10, d16 \n" "vaddw.s16 q11, q11, d17 \n" "vst1.32 {d20-d23}, [%3:128]!\n" // outptr2_s32 //############################################# //load inch kernel_3 k0-k7 "vdup.s8 d8, d25[0] \n" "vdup.s8 d9, d25[1] \n" "vdup.s8 d10, d25[2] \n" "vdup.s8 d11, d25[3] \n" "vdup.s8 d12, d25[4] \n" "vdup.s8 d13, d25[5] \n" "vdup.s8 d14, d25[6] \n" "vdup.s8 d15, d25[7] \n" //mla "vmull.s8 q8, d0, d8 \n" "vmlal.s8 q8, d1, d9 \n" "vmlal.s8 q8, d2, d10 \n" "vmlal.s8 q8, d3, d11 \n" "vmlal.s8 q8, d4, d12 \n" "vmlal.s8 q8, d5, d13 \n" "vmlal.s8 q8, d6, d14 \n" "vmlal.s8 q8, d7, d15 \n" //"pld [%4, #128] \n" "vld1.32 {d20-d23}, [%4:128] \n" // outptr3_s32 "vaddw.s16 q10, q10, d16 \n" "vaddw.s16 q11, q11, d17 \n" "vst1.32 {d20-d23}, [%4:128]!\n" // outptr3_s32 //next "subs %0, #1 \n" "bne 0b \n" : "=r"(nn), // %0 "=r"(outptr0), // %1 "=r"(outptr1), // %2 "=r"(outptr2), // %3 "=r"(outptr3), // %4 "=r"(r0), // %5 "=r"(r1), // %6 "=r"(r2), // %7 "=r"(r3), // %8 "=r"(r4), // %9 "=r"(r5), // %10 "=r"(r6), // %11 "=r"(r7) // %12 : "0"(nn), "1"(outptr0), "2"(outptr1), "3"(outptr2), "4"(outptr3), "5"(r0), "6"(r1), "7"(r2), "8"(r3), "9"(r4), "10"(r5), "11"(r6), "12"(r7) : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q10", "q11", "q13", "q14", "q15" );
很高兴能在这里讨论ARM NEON优化知识,上面这一大段代码是我在ncnn框架中实现的conv1x1s1 int8的最内层功能,实现inch 8,outch 4卷积计算。从中可以看出几乎未考虑到流水线的连贯性,希望通过展开讨论并优化这段代码,总结出neon汇编实现中需要主要的知识点,望各位大神多多发言。