Loosen sse read restrictions. Tested.

This commit is contained in:
Steve Checkoway
2006-12-11 13:26:12 +00:00
parent 6c9632bdc6
commit 02282d4a14
@@ -536,14 +536,16 @@ void Vector::FastSoundWrite( int32_t *dest, const int16_t *src, unsigned size, s
*(dest++) += *(src++) * volume; *(dest++) += *(src++) * volume;
} }
void Vector::FastSoundRead( int16_t *dest, const int32_t *src, unsigned size ) template<typename T>
static inline void Read( T load, int16_t *&dest, const int32_t *&src, unsigned &size ) __attribute__((always_inline));
template<typename T>
static inline void Read( T load, int16_t *&dest, const int32_t *&src, unsigned &size )
{ {
// Both dest and src are aligned. Still need to watch out for register spill.
__m128i zero = _mm_setzero_si128(); __m128i zero = _mm_setzero_si128();
while( size >= 8 ) while( size >= 8 )
{ {
__m128i data1 = _mm_load_si128( (__m128i *)(src + 0) ); __m128i data1 = load( (__m128i *)(src + 0) );
__m128i data2 = _mm_load_si128( (__m128i *)(src + 4) ); __m128i data2 = load( (__m128i *)(src + 4) );
__m128i mask1 = _mm_cmplt_epi32( data1, zero ); __m128i mask1 = _mm_cmplt_epi32( data1, zero );
__m128i mask2 = _mm_cmplt_epi32( data2, zero ); __m128i mask2 = _mm_cmplt_epi32( data2, zero );
__m128i t1 = _mm_srai_epi32( data1, 31 ); __m128i t1 = _mm_srai_epi32( data1, 31 );
@@ -566,8 +568,8 @@ void Vector::FastSoundRead( int16_t *dest, const int32_t *src, unsigned size )
} }
if( size ) if( size )
{ {
__m128i data1 = _mm_load_si128( (__m128i *)(src + 0) ); __m128i data1 = load( (__m128i *)(src + 0) );
__m128i data2 = size > 4 ? _mm_load_si128( (__m128i *)(src + 4) ) : zero; __m128i data2 = size > 4 ? load( (__m128i *)(src + 4) ) : zero;
__m128i mask1 = _mm_cmplt_epi32( data1, zero ); __m128i mask1 = _mm_cmplt_epi32( data1, zero );
__m128i mask2 = _mm_cmplt_epi32( data2, zero ); __m128i mask2 = _mm_cmplt_epi32( data2, zero );
__m128i t1 = _mm_srai_epi32( data1, 31 ); __m128i t1 = _mm_srai_epi32( data1, 31 );
@@ -591,7 +593,27 @@ void Vector::FastSoundRead( int16_t *dest, const int32_t *src, unsigned size )
} }
} }
void Vector::FastSoundRead( float *dest, const int32_t *src, unsigned size ) void Vector::FastSoundRead( int16_t *dest, const int32_t *src, unsigned size )
{
while( (intptr_t(dest) & 0xF) && size )
{
// Misaligned stores are very slow.
*dest++ = max( -32768, min(*src++>>8, 32767) );
--size;
}
// Specialize loads.
if( intptr_t(src) & 0xF )
Read( _mm_loadu_si128, dest, src, size );
else
Read( _mm_load_si128, dest, src, size );
while( size-- )
*dest++ = max( -32768, min(*src++>>8, 32767) );
}
template<typename T>
static inline void Read( T load, float *&dest, const int32_t *&src, unsigned &size ) __attribute__((always_inline));
template<typename T>
static inline void Read( T load, float *&dest, const int32_t *&src, unsigned &size )
{ {
/* m = -32768; M = 32767 /* m = -32768; M = 32767
* (x-2^8*m)(1-(-1))/(2^8*M-2^8*m)+(-1) * (x-2^8*m)(1-(-1))/(2^8*M-2^8*m)+(-1)
@@ -605,7 +627,7 @@ void Vector::FastSoundRead( float *dest, const int32_t *src, unsigned size )
while( size >= 4 ) while( size >= 4 )
{ {
__m128i data = _mm_sub_epi32( _mm_load_si128((__m128i *)src), l1 ); __m128i data = _mm_sub_epi32( load((__m128i *)src), l1 );
__m128 result = _mm_cvtepi32_ps( data ); __m128 result = _mm_cvtepi32_ps( data );
result = _mm_add_ps( _mm_mul_ps(result, scale), l2 ); result = _mm_add_ps( _mm_mul_ps(result, scale), l2 );
@@ -620,7 +642,7 @@ void Vector::FastSoundRead( float *dest, const int32_t *src, unsigned size )
__m128i storeMask = _mm_set_epi8( 0, 0, 0, 0, X(3), X(3), X(3), X(3), __m128i storeMask = _mm_set_epi8( 0, 0, 0, 0, X(3), X(3), X(3), X(3),
X(2), X(2), X(2), X(2), -1, -1, -1, -1 ); X(2), X(2), X(2), X(2), -1, -1, -1, -1 );
#undef X #undef X
__m128i data = _mm_sub_epi32( _mm_load_si128((__m128i *)src), l1 ); __m128i data = _mm_sub_epi32( load((__m128i *)src), l1 );
__m128 result = _mm_cvtepi32_ps( data ); __m128 result = _mm_cvtepi32_ps( data );
result = _mm_add_ps( _mm_mul_ps(result, scale), l2 ); result = _mm_add_ps( _mm_mul_ps(result, scale), l2 );
@@ -628,6 +650,23 @@ void Vector::FastSoundRead( float *dest, const int32_t *src, unsigned size )
_mm_maskmoveu_si128( (__m128i)result, storeMask, (char *)dest ); _mm_maskmoveu_si128( (__m128i)result, storeMask, (char *)dest );
} }
} }
void Vector::FastSoundRead( float *dest, const int32_t *src, unsigned size )
{
while( (intptr_t(dest) & 0xF) && size )
{
// Misaligned stores are very slow.
*dest++ = float( *src++ + 32768*256 ) * 1.1921110856794079500e-7f - 1.0f;
--size;
}
// Specialize loads.
if( intptr_t(src) & 0xF )
Read( _mm_loadu_si128, dest, src, size );
else
Read( _mm_load_si128, dest, src, size );
while( size-- )
*dest++ = float( *src++ + 32768*256 ) * 1.1921110856794079500e-7f - 1.0f;;
}
#else #else
#error huh? #error huh?
#endif #endif