Blame gst-libs/gst/audio/audio-resampler-x86-sse41.c

Packit 971217
/* GStreamer
Packit 971217
 * Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#  include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include "audio-resampler-x86-sse41.h"
Packit 971217
Packit 971217
#if 0
Packit 971217
#define __SSE4_1__
Packit 971217
#pragma GCC target("sse4.1")
Packit 971217
#endif
Packit 971217
Packit 971217
#if defined (__x86_64__) && \
Packit 971217
    defined (HAVE_SMMINTRIN_H) && defined (HAVE_EMMINTRIN_H) && \
Packit 971217
    defined (__SSE4_1__)
Packit 971217
Packit 971217
#include <emmintrin.h>
Packit 971217
#include <smmintrin.h>
Packit 971217
Packit 971217
static inline void
Packit 971217
inner_product_gint32_full_1_sse41 (gint32 * o, const gint32 * a,
Packit 971217
    const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
Packit 971217
{
Packit 971217
  gint i = 0;
Packit 971217
  __m128i sum, ta, tb;
Packit 971217
  gint64 res;
Packit 971217
Packit 971217
  sum = _mm_setzero_si128 ();
Packit 971217
Packit 971217
  for (; i < len; i += 8) {
Packit 971217
    ta = _mm_loadu_si128 ((__m128i *) (a + i));
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (b + i));
Packit 971217
Packit 971217
    sum =
Packit 971217
        _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum =
Packit 971217
        _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
Packit 971217
    ta = _mm_loadu_si128 ((__m128i *) (a + i + 4));
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (b + i + 4));
Packit 971217
Packit 971217
    sum =
Packit 971217
        _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum =
Packit 971217
        _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
  }
Packit 971217
  sum = _mm_add_epi64 (sum, _mm_unpackhi_epi64 (sum, sum));
Packit 971217
  res = _mm_cvtsi128_si64 (sum);
Packit 971217
Packit 971217
  res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
Packit 971217
  *o = CLAMP (res, G_MININT32, G_MAXINT32);
Packit 971217
}
Packit 971217
Packit 971217
static inline void
Packit 971217
inner_product_gint32_linear_1_sse41 (gint32 * o, const gint32 * a,
Packit 971217
    const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
Packit 971217
{
Packit 971217
  gint i = 0;
Packit 971217
  gint64 res;
Packit 971217
  __m128i sum[2], ta, tb;
Packit 971217
  __m128i f = _mm_loadu_si128 ((__m128i *) icoeff);
Packit 971217
  const gint32 *c[2] = { (gint32 *) ((gint8 *) b + 0 * bstride),
Packit 971217
    (gint32 *) ((gint8 *) b + 1 * bstride)
Packit 971217
  };
Packit 971217
Packit 971217
  sum[0] = sum[1] = _mm_setzero_si128 ();
Packit 971217
Packit 971217
  for (; i < len; i += 4) {
Packit 971217
    ta = _mm_loadu_si128 ((__m128i *) (a + i));
Packit 971217
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (c[0] + i));
Packit 971217
    sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (c[1] + i));
Packit 971217
    sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
  }
Packit 971217
  sum[0] = _mm_srli_epi64 (sum[0], PRECISION_S32);
Packit 971217
  sum[1] = _mm_srli_epi64 (sum[1], PRECISION_S32);
Packit 971217
  sum[0] =
Packit 971217
      _mm_mul_epi32 (sum[0], _mm_shuffle_epi32 (f, _MM_SHUFFLE (0, 0, 0, 0)));
Packit 971217
  sum[1] =
Packit 971217
      _mm_mul_epi32 (sum[1], _mm_shuffle_epi32 (f, _MM_SHUFFLE (1, 1, 1, 1)));
Packit 971217
  sum[0] = _mm_add_epi64 (sum[0], sum[1]);
Packit 971217
  sum[0] = _mm_add_epi64 (sum[0], _mm_unpackhi_epi64 (sum[0], sum[0]));
Packit 971217
  res = _mm_cvtsi128_si64 (sum[0]);
Packit 971217
Packit 971217
  res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
Packit 971217
  *o = CLAMP (res, G_MININT32, G_MAXINT32);
Packit 971217
}
Packit 971217
Packit 971217
static inline void
Packit 971217
inner_product_gint32_cubic_1_sse41 (gint32 * o, const gint32 * a,
Packit 971217
    const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
Packit 971217
{
Packit 971217
  gint i = 0;
Packit 971217
  gint64 res;
Packit 971217
  __m128i sum[4], ta, tb;
Packit 971217
  __m128i f = _mm_loadu_si128 ((__m128i *) icoeff);
Packit 971217
  const gint32 *c[4] = { (gint32 *) ((gint8 *) b + 0 * bstride),
Packit 971217
    (gint32 *) ((gint8 *) b + 1 * bstride),
Packit 971217
    (gint32 *) ((gint8 *) b + 2 * bstride),
Packit 971217
    (gint32 *) ((gint8 *) b + 3 * bstride)
Packit 971217
  };
Packit 971217
Packit 971217
  sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_si128 ();
Packit 971217
Packit 971217
  for (; i < len; i += 4) {
Packit 971217
    ta = _mm_loadu_si128 ((__m128i *) (a + i));
Packit 971217
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (c[0] + i));
Packit 971217
    sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (c[1] + i));
Packit 971217
    sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (c[2] + i));
Packit 971217
    sum[2] = _mm_add_epi64 (sum[2], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum[2] = _mm_add_epi64 (sum[2], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
Packit 971217
    tb = _mm_load_si128 ((__m128i *) (c[3] + i));
Packit 971217
    sum[3] = _mm_add_epi64 (sum[3], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
Packit 971217
            _mm_unpacklo_epi32 (tb, tb)));
Packit 971217
    sum[3] = _mm_add_epi64 (sum[3], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
Packit 971217
            _mm_unpackhi_epi32 (tb, tb)));
Packit 971217
  }
Packit 971217
  sum[0] = _mm_srli_epi64 (sum[0], PRECISION_S32);
Packit 971217
  sum[1] = _mm_srli_epi64 (sum[1], PRECISION_S32);
Packit 971217
  sum[2] = _mm_srli_epi64 (sum[2], PRECISION_S32);
Packit 971217
  sum[3] = _mm_srli_epi64 (sum[3], PRECISION_S32);
Packit 971217
  sum[0] =
Packit 971217
      _mm_mul_epi32 (sum[0], _mm_shuffle_epi32 (f, _MM_SHUFFLE (0, 0, 0, 0)));
Packit 971217
  sum[1] =
Packit 971217
      _mm_mul_epi32 (sum[1], _mm_shuffle_epi32 (f, _MM_SHUFFLE (1, 1, 1, 1)));
Packit 971217
  sum[2] =
Packit 971217
      _mm_mul_epi32 (sum[2], _mm_shuffle_epi32 (f, _MM_SHUFFLE (2, 2, 2, 2)));
Packit 971217
  sum[3] =
Packit 971217
      _mm_mul_epi32 (sum[3], _mm_shuffle_epi32 (f, _MM_SHUFFLE (3, 3, 3, 3)));
Packit 971217
  sum[0] = _mm_add_epi64 (sum[0], sum[1]);
Packit 971217
  sum[2] = _mm_add_epi64 (sum[2], sum[3]);
Packit 971217
  sum[0] = _mm_add_epi64 (sum[0], sum[2]);
Packit 971217
  sum[0] = _mm_add_epi64 (sum[0], _mm_unpackhi_epi64 (sum[0], sum[0]));
Packit 971217
  res = _mm_cvtsi128_si64 (sum[0]);
Packit 971217
Packit 971217
  res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
Packit 971217
  *o = CLAMP (res, G_MININT32, G_MAXINT32);
Packit 971217
}
Packit 971217
Packit 971217
MAKE_RESAMPLE_FUNC (gint32, full, 1, sse41);
Packit 971217
MAKE_RESAMPLE_FUNC (gint32, linear, 1, sse41);
Packit 971217
MAKE_RESAMPLE_FUNC (gint32, cubic, 1, sse41);
Packit 971217
Packit 971217
#endif