simd-detect-runtime.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c
  2. --- a/media/libspeex_resampler/src/resample.c
  3. +++ b/media/libspeex_resampler/src/resample.c
  4. @@ -92,23 +92,17 @@ static void speex_free (void *ptr) {free
  5. #define IMAX(a,b) ((a) > (b) ? (a) : (b))
  6. #define IMIN(a,b) ((a) < (b) ? (a) : (b))
  7. #ifndef NULL
  8. #define NULL 0
  9. #endif
  10. -#ifdef _USE_SSE
  11. -#include "resample_sse.h"
  12. -#endif
  13. -
  14. -#ifdef _USE_NEON
  15. -#include "resample_neon.h"
  16. -#endif
  17. +#include "simd_detect.h"
  18. /* Numer of elements to allocate on the stack */
  19. #ifdef VAR_ARRAYS
  20. #define FIXED_STACK_ALLOC 8192
  21. #else
  22. #define FIXED_STACK_ALLOC 1024
  23. #endif
  24. @@ -344,17 +338,19 @@ static int resampler_basic_direct_single
  25. const spx_uint32_t den_rate = st->den_rate;
  26. spx_word32_t sum;
  27. while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
  28. {
  29. const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
  30. const spx_word16_t *iptr = & in[last_sample];
  31. -#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
  32. +#ifdef OVERRIDE_INNER_PRODUCT_SINGLE
  33. + if (!moz_speex_have_single_simd()) {
  34. +#endif
  35. int j;
  36. sum = 0;
  37. for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]);
  38. /* This code is slower on most DSPs which have only 2 accumulators.
  39. Plus this this forces truncation to 32 bits and you lose the HW guard bits.
  40. I think we can trust the compiler and let it vectorize and/or unroll itself.
  41. spx_word32_t accum[4] = {0,0,0,0};
  42. @@ -362,18 +358,20 @@ static int resampler_basic_direct_single
  43. accum[0] += MULT16_16(sinct[j], iptr[j]);
  44. accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);
  45. accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);
  46. accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);
  47. }
  48. sum = accum[0] + accum[1] + accum[2] + accum[3];
  49. */
  50. sum = SATURATE32PSHR(sum, 15, 32767);
  51. -#else
  52. +#ifdef OVERRIDE_INNER_PRODUCT_SINGLE
  53. + } else {
  54. sum = inner_product_single(sinct, iptr, N);
  55. + }
  56. #endif
  57. out[out_stride * out_sample++] = sum;
  58. last_sample += int_advance;
  59. samp_frac_num += frac_advance;
  60. if (samp_frac_num >= den_rate)
  61. {
  62. samp_frac_num -= den_rate;
  63. @@ -402,29 +400,33 @@ static int resampler_basic_direct_double
  64. const spx_uint32_t den_rate = st->den_rate;
  65. double sum;
  66. while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
  67. {
  68. const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
  69. const spx_word16_t *iptr = & in[last_sample];
  70. -#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
  71. +#ifdef OVERRIDE_INNER_PRODUCT_DOUBLE
  72. + if(moz_speex_have_double_simd()) {
  73. +#endif
  74. int j;
  75. double accum[4] = {0,0,0,0};
  76. for(j=0;j<N;j+=4) {
  77. accum[0] += sinct[j]*iptr[j];
  78. accum[1] += sinct[j+1]*iptr[j+1];
  79. accum[2] += sinct[j+2]*iptr[j+2];
  80. accum[3] += sinct[j+3]*iptr[j+3];
  81. }
  82. sum = accum[0] + accum[1] + accum[2] + accum[3];
  83. -#else
  84. +#ifdef OVERRIDE_INNER_PRODUCT_DOUBLE
  85. + } else {
  86. sum = inner_product_double(sinct, iptr, N);
  87. + }
  88. #endif
  89. out[out_stride * out_sample++] = PSHR32(sum, 15);
  90. last_sample += int_advance;
  91. samp_frac_num += frac_advance;
  92. if (samp_frac_num >= den_rate)
  93. {
  94. samp_frac_num -= den_rate;
  95. @@ -458,34 +460,38 @@ static int resampler_basic_interpolate_s
  96. #ifdef FIXED_POINT
  97. const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
  98. #else
  99. const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
  100. #endif
  101. spx_word16_t interp[4];
  102. -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
  103. +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
  104. + if (!moz_speex_have_single_simd()) {
  105. +#endif
  106. int j;
  107. spx_word32_t accum[4] = {0,0,0,0};
  108. for(j=0;j<N;j++) {
  109. const spx_word16_t curr_in=iptr[j];
  110. accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
  111. accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
  112. accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
  113. accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
  114. }
  115. cubic_coef(frac, interp);
  116. sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1));
  117. sum = SATURATE32PSHR(sum, 15, 32767);
  118. -#else
  119. +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
  120. + } else {
  121. cubic_coef(frac, interp);
  122. sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
  123. + }
  124. #endif
  125. out[out_stride * out_sample++] = sum;
  126. last_sample += int_advance;
  127. samp_frac_num += frac_advance;
  128. if (samp_frac_num >= den_rate)
  129. {
  130. samp_frac_num -= den_rate;
  131. @@ -521,33 +527,37 @@ static int resampler_basic_interpolate_d
  132. #ifdef FIXED_POINT
  133. const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
  134. #else
  135. const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
  136. #endif
  137. spx_word16_t interp[4];
  138. -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
  139. +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
  140. + if (!moz_speex_have_double_simd()) {
  141. +#endif
  142. int j;
  143. double accum[4] = {0,0,0,0};
  144. for(j=0;j<N;j++) {
  145. const double curr_in=iptr[j];
  146. accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
  147. accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
  148. accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
  149. accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
  150. }
  151. cubic_coef(frac, interp);
  152. sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
  153. -#else
  154. +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
  155. + } else {
  156. cubic_coef(frac, interp);
  157. sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
  158. + }
  159. #endif
  160. out[out_stride * out_sample++] = PSHR32(sum,15);
  161. last_sample += int_advance;
  162. samp_frac_num += frac_advance;
  163. if (samp_frac_num >= den_rate)
  164. {
  165. samp_frac_num -= den_rate;
  166. diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resampler/src/resample_neon.c
  167. --- a/media/libspeex_resampler/src/resample_neon.c
  168. +++ b/media/libspeex_resampler/src/resample_neon.c
  169. @@ -31,16 +31,18 @@
  170. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  171. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  172. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  173. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  174. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  175. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  176. */
  177. +#include "simd_detect.h"
  178. +
  179. #include <arm_neon.h>
  180. #ifdef FIXED_POINT
  181. #ifdef __thumb2__
  182. static inline int32_t saturate_32bit_to_16bit(int32_t a) {
  183. int32_t ret;
  184. asm ("ssat %[ret], #16, %[a]"
  185. : [ret] "=&r" (ret)
  186. @@ -60,17 +62,17 @@ static inline int32_t saturate_32bit_to_
  187. return ret;
  188. }
  189. #endif
  190. #undef WORD2INT
  191. #define WORD2INT(x) (saturate_32bit_to_16bit(x))
  192. #define OVERRIDE_INNER_PRODUCT_SINGLE
  193. /* Only works when len % 4 == 0 */
  194. -static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
  195. +int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
  196. {
  197. int32_t ret;
  198. uint32_t remainder = len % 16;
  199. len = len - remainder;
  200. asm volatile (" cmp %[len], #0\n"
  201. " bne 1f\n"
  202. " vld1.16 {d16}, [%[b]]!\n"
  203. @@ -134,17 +136,17 @@ static inline int32_t saturate_float_to_
  204. : "q0");
  205. return ret;
  206. }
  207. #undef WORD2INT
  208. #define WORD2INT(x) (saturate_float_to_16bit(x))
  209. #define OVERRIDE_INNER_PRODUCT_SINGLE
  210. /* Only works when len % 4 == 0 */
  211. -static inline float inner_product_single(const float *a, const float *b, unsigned int len)
  212. +float inner_product_single(const float *a, const float *b, unsigned int len)
  213. {
  214. float ret;
  215. uint32_t remainder = len % 16;
  216. len = len - remainder;
  217. asm volatile (" cmp %[len], #0\n"
  218. " bne 1f\n"
  219. " vld1.32 {q4}, [%[b]]!\n"
  220. diff --git a/media/libspeex_resampler/src/resample_sse.c b/media/libspeex_resampler/src/resample_sse.c
  221. --- a/media/libspeex_resampler/src/resample_sse.c
  222. +++ b/media/libspeex_resampler/src/resample_sse.c
  223. @@ -29,37 +29,39 @@
  224. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  225. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  226. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  227. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  228. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  229. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  230. */
  231. +#include "simd_detect.h"
  232. +
  233. #include <xmmintrin.h>
  234. #define OVERRIDE_INNER_PRODUCT_SINGLE
  235. -static inline float inner_product_single(const float *a, const float *b, unsigned int len)
  236. +float inner_product_single(const float *a, const float *b, unsigned int len)
  237. {
  238. int i;
  239. float ret;
  240. __m128 sum = _mm_setzero_ps();
  241. for (i=0;i<len;i+=8)
  242. {
  243. sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)));
  244. sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)));
  245. }
  246. sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
  247. sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
  248. _mm_store_ss(&ret, sum);
  249. return ret;
  250. }
  251. #define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
  252. -static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
  253. +float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
  254. int i;
  255. float ret;
  256. __m128 sum = _mm_setzero_ps();
  257. __m128 f = _mm_loadu_ps(frac);
  258. for(i=0;i<len;i+=2)
  259. {
  260. sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)));
  261. sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)));
  262. @@ -70,17 +72,17 @@ static inline float interpolate_product_
  263. _mm_store_ss(&ret, sum);
  264. return ret;
  265. }
  266. #ifdef _USE_SSE2
  267. #include <emmintrin.h>
  268. #define OVERRIDE_INNER_PRODUCT_DOUBLE
  269. -static inline double inner_product_double(const float *a, const float *b, unsigned int len)
  270. +double inner_product_double(const float *a, const float *b, unsigned int len)
  271. {
  272. int i;
  273. double ret;
  274. __m128d sum = _mm_setzero_pd();
  275. __m128 t;
  276. for (i=0;i<len;i+=8)
  277. {
  278. t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i));
  279. @@ -92,17 +94,17 @@ static inline double inner_product_doubl
  280. sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
  281. }
  282. sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum));
  283. _mm_store_sd(&ret, sum);
  284. return ret;
  285. }
  286. #define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
  287. -static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
  288. +double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
  289. int i;
  290. double ret;
  291. __m128d sum;
  292. __m128d sum1 = _mm_setzero_pd();
  293. __m128d sum2 = _mm_setzero_pd();
  294. __m128 f = _mm_loadu_ps(frac);
  295. __m128d f1 = _mm_cvtps_pd(f);
  296. __m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f));