@@ -49,6 +49,8 @@ void hvx_mul_f32(const uint8_t * restrict src0,
4949 FARF (HIGH , "hvx_mul_f32: unaligned loop in hvx op, possibly slower execution\n" );
5050 }
5151
52+
53+ bool handled_leftover = false;
5254 if (0 == unaligned_loop ) {
5355 HVX_Vector * restrict vec_in1 = (HVX_Vector * ) src0 ;
5456 HVX_Vector * restrict vec_in2 = (HVX_Vector * ) src1 ;
@@ -60,18 +62,59 @@ void hvx_mul_f32(const uint8_t * restrict src0,
6062 * vec_out ++ = Q6_Vsf_equals_Vqf32 (v );
6163 }
6264 } else {
65+ int step_of_1 = num_elems_whole >> 5 ; // divby 32, because 32 float = 128 bytes per HVX vector
66+ int leftover_size = left_over * sizeof (float );
67+
68+
69+ HVX_Vector * restrict vec_in1 = (HVX_Vector * ) src0 ;
70+ HVX_Vector * restrict vec_in2 = (HVX_Vector * ) src1 ;
71+ HVX_UVector * restrict vec_out = (HVX_UVector * ) dst ;
72+
73+ HVX_Vector slinep ;
74+ HVX_Vector slinec ;
75+ HVX_Vector sline ;
76+ HVX_Vector sline2p ;
77+ HVX_Vector sline2c ;
78+ HVX_Vector sline2 ;
79+
80+ slinep = * vec_in1 ++ ;
81+ sline2p = * vec_in2 ++ ;
6382 #pragma unroll(4)
64- for (int i = 0 ; i < num_elems_whole ; i += VLEN_FP32 ) {
65- HVX_Vector in1 = * (HVX_UVector * ) (src0 + i * SIZEOF_FP32 );
66- HVX_Vector in2 = * (HVX_UVector * ) (src1 + i * SIZEOF_FP32 );
83+ for (int i = step_of_1 - 1 ; i > 0 ; i -- ) {
84+ slinec = * vec_in1 ++ ;
85+ sline2c = * vec_in2 ++ ;
86+ sline = Q6_V_valign_VVR (slinec , slinep , (size_t ) src0 );
87+ sline2 = Q6_V_valign_VVR (sline2c , sline2p , (size_t ) src1 );
88+
89+ * ((HVX_UVector * ) (vec_out ++ )) = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (sline , sline2 ));
90+ slinep = slinec ;
91+ sline2p = sline2c ;
92+ }
93+ if (step_of_1 > 1 ) {
94+ slinec = htp_is_aligned (vec_in1 , VLEN ) && left_over == 0 ? slinep : * vec_in1 ++ ;
95+ sline2c = htp_is_aligned (vec_in2 , VLEN ) && left_over == 0 ? sline2p : * vec_in2 ++ ;
96+
97+ sline = Q6_V_valign_VVR (slinec , slinep , (size_t ) src0 );
98+ sline2 = Q6_V_valign_VVR (sline2c , sline2p , (size_t ) src1 );
99+ * ((HVX_UVector * ) (vec_out ++ )) = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (sline , sline2 ));
100+ slinep = slinec ;
101+ sline2p = sline2c ;
102+ }
103+ if (left_over > 0 ) {
104+ slinec = (is_in_one_chunk (vec_in1 , leftover_size , VLEN ) ? slinep : * vec_in1 ++ );
67105
68- HVX_Vector out = Q6_Vqf32_vmpy_VsfVsf (in1 , in2 );
106+ sline = Q6_V_valign_VVR (slinec , slinep , (size_t ) src0 );
107+ sline2c = (is_in_one_chunk (vec_in2 , leftover_size , VLEN ) ? sline2p : * vec_in2 ++ );
108+ sline2 = Q6_V_valign_VVR (sline2c , sline2p , (size_t ) src1 );
69109
70- * (HVX_UVector * ) (dst + i * SIZEOF_FP32 ) = Q6_Vsf_equals_Vqf32 (out );
110+ HVX_Vector out = Q6_Vqf32_vmpy_VsfVsf (sline , sline2 );
111+ hvx_vec_store_u (vec_out , leftover_size , Q6_Vsf_equals_Vqf32 (out ));
112+ handled_leftover = true;
71113 }
72114 }
73115
74- if (left_over > 0 ) {
116+
117+ if (left_over > 0 && !handled_leftover ) {
75118 const float * src0f = (const float * ) src0 + num_elems_whole ;
76119 const float * src1f = (const float * ) src1 + num_elems_whole ;
77120 float * dstf = (float * ) dst + num_elems_whole ;
@@ -464,7 +507,7 @@ void hvx_mul_scalar_f32(const uint8_t * restrict src, const float val, uint8_t *
464507 }
465508
466509 HVX_Vector val_vec = hvx_vec_splat_fp32 (val );
467-
510+ bool handled_leftover = false;
468511 if (0 == unaligned_loop ) {
469512 HVX_Vector * restrict vec_in1 = (HVX_Vector * ) src ;
470513 HVX_Vector * restrict vec_out = (HVX_Vector * ) dst ;
@@ -475,17 +518,47 @@ void hvx_mul_scalar_f32(const uint8_t * restrict src, const float val, uint8_t *
475518 * vec_out ++ = Q6_Vsf_equals_Vqf32 (v );
476519 }
477520 } else {
521+ int step_of_1 = num_elems >> 5 ; // divby 32, because 32 float = 128 bytes per HVX vector
522+ int leftover_size = left_over * sizeof (float );
523+
524+ HVX_Vector * input_v_ptr = (HVX_Vector * ) src ;
525+ HVX_UVector * output_v_ptr = (HVX_UVector * ) dst ;
526+
527+ HVX_Vector slinep ;
528+ HVX_Vector slinec ;
529+ HVX_Vector sline ;
530+
531+ slinep = * input_v_ptr ++ ;
532+
478533 #pragma unroll(4)
479- for (int i = 0 ; i < num_elems_whole ; i += VLEN_FP32 ) {
480- HVX_Vector in = * (HVX_UVector * ) (src + i * SIZEOF_FP32 );
534+ for (int i = step_of_1 - 1 ; i > 0 ; i -- ) {
535+ slinec = * input_v_ptr ++ ;
536+ sline = Q6_V_valign_VVR (slinec , slinep , (size_t ) src );
537+ * ((HVX_UVector * ) (output_v_ptr ++ )) = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (sline , val_vec ));
538+ /* Prepare slinep for next iteration */
539+ slinep = slinec ;
540+ }
481541
482- HVX_Vector out = Q6_Vqf32_vmpy_VsfVsf (in , val_vec );
542+ if (step_of_1 > 0 ) {
543+ slinec = htp_is_aligned (input_v_ptr , VLEN ) && left_over == 0 ? slinep : * input_v_ptr ++ ;
544+ sline = Q6_V_valign_VVR (slinec , slinep , (size_t ) src );
545+ * ((HVX_UVector * ) (output_v_ptr ++ )) = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (sline , val_vec ));
483546
484- * (HVX_UVector * ) (dst + i * SIZEOF_FP32 ) = Q6_Vsf_equals_Vqf32 (out );
547+ slinep = slinec ;
548+ }
549+
550+ if (leftover_size > 0 ) {
551+ slinec = (is_in_one_chunk (input_v_ptr , leftover_size , VLEN ) ? slinep : * input_v_ptr ++ );
552+
553+ sline = Q6_V_valign_VVR (slinec , slinep , (size_t ) src );
554+
555+ HVX_Vector sout = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (sline , val_vec ));
556+ hvx_vec_store_u (output_v_ptr , leftover_size , sout );
557+ handled_leftover = true;
485558 }
486559 }
487560
488- if (left_over > 0 ) {
561+ if (left_over > 0 && ! handled_leftover ) {
489562 const float * srcf = (const float * ) src + num_elems_whole ;
490563 float * dstf = (float * ) dst + num_elems_whole ;
491564
0 commit comments