Specialize on aligned loads for sse since misaligned loads are much slower.
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
#include "RageUtil.h"
|
#include "RageUtil.h"
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
#ifdef USE_VEC
|
#if defined(USE_VEC)
|
||||||
#if defined(__VEC__)
|
#if defined(__VEC__)
|
||||||
#include <vecLib/vecLib.h>
|
#include <vecLib/vecLib.h>
|
||||||
#ifndef __VECLIBTYPES__
|
#ifndef __VECLIBTYPES__
|
||||||
@@ -398,9 +398,9 @@ void Vector::FastSoundRead( float *dest, const int32_t *src, unsigned size )
|
|||||||
vec_ste( result, 0, dest++ );
|
vec_ste( result, 0, dest++ );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(__SSE__)
|
#elif defined(__SSE2__)
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
// This might even be portable to other sysems since it uses Intel's intrinsics.
|
// This is portable to other sysems since it uses Intel's intrinsics.
|
||||||
|
|
||||||
bool Vector::CheckForVector()
|
bool Vector::CheckForVector()
|
||||||
{
|
{
|
||||||
@@ -408,6 +408,31 @@ bool Vector::CheckForVector()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename load>
|
||||||
|
static inline void Write( int32_t *&dest, const int16_t *&src,
|
||||||
|
unsigned &size, __m128i vol ) __attribute__((always_inline));
|
||||||
|
template<typename T>
|
||||||
|
inline void Write( T load, int32_t *&dest, const int16_t *&src, unsigned &size, __m128i vol )
|
||||||
|
{
|
||||||
|
// There are only 8 XMM registers so no 4x unrolling
|
||||||
|
while( size >= 8 )
|
||||||
|
{
|
||||||
|
__m128i data = load( (__m128i *)src );
|
||||||
|
__m128i hi = _mm_mulhi_epi16( data, vol );
|
||||||
|
__m128i low = _mm_mullo_epi16( data, vol );
|
||||||
|
__m128i result1 = _mm_unpacklo_epi16( low, hi );
|
||||||
|
__m128i result2 = _mm_unpackhi_epi16( low, hi );
|
||||||
|
|
||||||
|
result1 = _mm_add_epi32( result1, *(__m128i *)(dest + 0) );
|
||||||
|
result2 = _mm_add_epi32( result2, *(__m128i *)(dest + 4) );
|
||||||
|
_mm_store_si128( (__m128i *)(dest + 0), result1 );
|
||||||
|
_mm_store_si128( (__m128i *)(dest + 4), result2 );
|
||||||
|
src += 8;
|
||||||
|
dest += 8;
|
||||||
|
size -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Vector::FastSoundWrite( int32_t *dest, const int16_t *src, unsigned size, short volume )
|
void Vector::FastSoundWrite( int32_t *dest, const int16_t *src, unsigned size, short volume )
|
||||||
{
|
{
|
||||||
if( size == 0 )
|
if( size == 0 )
|
||||||
@@ -420,26 +445,12 @@ void Vector::FastSoundWrite( int32_t *dest, const int16_t *src, unsigned size, s
|
|||||||
--size;
|
--size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are only 8 XMM registers so no 4x unrolling
|
|
||||||
__m128i vol = _mm_set1_epi16( volume );
|
__m128i vol = _mm_set1_epi16( volume );
|
||||||
|
// Misaligned loads are slower so specialize to aligned loads when possible.
|
||||||
while( size >= 8 )
|
if( intptr_t(src) & 0xF )
|
||||||
{
|
Write( _mm_loadu_si128, dest, src, size, vol );
|
||||||
// Aligned stores, possibly misaligned loads.
|
else
|
||||||
__m128i data = _mm_loadu_si128( (__m128i *)src );
|
Write( _mm_load_si128, dest, src, size, vol );
|
||||||
__m128i hi = _mm_mulhi_epi16( data, vol );
|
|
||||||
__m128i low = _mm_mullo_epi16( data, vol );
|
|
||||||
__m128i result1 = _mm_unpacklo_epi16( low, hi );
|
|
||||||
__m128i result2 = _mm_unpackhi_epi16( low, hi );
|
|
||||||
|
|
||||||
result1 = _mm_add_epi32( result1, *(__m128i *)(dest + 0) );
|
|
||||||
result2 = _mm_add_epi32( result2, *(__m128i *)(dest + 4) );
|
|
||||||
_mm_store_si128( (__m128i *)(dest + 0), result1 );
|
|
||||||
_mm_store_si128( (__m128i *)(dest + 4), result2 );
|
|
||||||
src += 8;
|
|
||||||
dest += 8;
|
|
||||||
size -= 8;
|
|
||||||
}
|
|
||||||
while( size-- )
|
while( size-- )
|
||||||
*(dest++) += *(src++) * volume;
|
*(dest++) += *(src++) * volume;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef VECTOR_HELPER_H
|
#ifndef VECTOR_HELPER_H
|
||||||
#define VECTOR_HELPER_H
|
#define VECTOR_HELPER_H
|
||||||
|
|
||||||
#if defined(__VEC__) || defined(__SSE__)
|
#if ( defined(__VEC__) || (defined(__SSE__) && defined(__SSE2__)) ) && defined(__GNUC__)
|
||||||
namespace Vector
|
namespace Vector
|
||||||
{
|
{
|
||||||
bool CheckForVector();
|
bool CheckForVector();
|
||||||
|
|||||||
Reference in New Issue
Block a user