Improve the leftover and realignment mixing loops
Using a mask helps the compiler recognize that the leftover (any remaining non- multiple-of-4) and realignment loops will only have 3 iterations at most, which it can unroll or otherwise make more meaningful optimizations for. Previously it would try to vectorize and partially unroll the loops, which is wasteful when there would never be enough to vectorize.
This commit is contained in:
@@ -219,7 +219,7 @@ void Mix_<NEONTag>(const al::span<const float> InSamples, const al::span<FloatBu
|
||||
{
|
||||
const float delta{(Counter > 0) ? 1.0f / static_cast<float>(Counter) : 0.0f};
|
||||
const auto min_len = minz(Counter, InSamples.size());
|
||||
const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size());
|
||||
const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size()) - min_len;
|
||||
for(FloatBufferLine &output : OutBuffer)
|
||||
{
|
||||
float *RESTRICT dst{al::assume_aligned<16>(output.data()+OutPos)};
|
||||
@@ -258,7 +258,7 @@ void Mix_<NEONTag>(const al::span<const float> InSamples, const al::span<FloatBu
|
||||
step_count = vgetq_lane_f32(step_count4, 0);
|
||||
}
|
||||
/* Mix with applying left over gain steps that aren't aligned multiples of 4. */
|
||||
for(;pos != min_len;++pos)
|
||||
for(uint_fast32_t leftover{min_len&3};leftover;++pos,--leftover)
|
||||
{
|
||||
dst[pos] += InSamples[pos] * (gain + step*step_count);
|
||||
step_count += 1.0f;
|
||||
@@ -269,7 +269,7 @@ void Mix_<NEONTag>(const al::span<const float> InSamples, const al::span<FloatBu
|
||||
gain += step*step_count;
|
||||
|
||||
/* Mix until pos is aligned with 4 or the mix is done. */
|
||||
for(;pos != aligned_len;++pos)
|
||||
for(uint_fast32_t leftover{aligned_len&3};leftover;++pos,--leftover)
|
||||
dst[pos] += InSamples[pos] * gain;
|
||||
}
|
||||
*CurrentGains = gain;
|
||||
@@ -289,7 +289,7 @@ void Mix_<NEONTag>(const al::span<const float> InSamples, const al::span<FloatBu
|
||||
pos += 4;
|
||||
} while(--todo);
|
||||
}
|
||||
for(;pos != InSamples.size();++pos)
|
||||
for(uint_fast32_t leftover{InSamples.size()&3};leftover;++pos,--leftover)
|
||||
dst[pos] += InSamples[pos] * gain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ void Mix_<SSETag>(const al::span<const float> InSamples, const al::span<FloatBuf
|
||||
{
|
||||
const float delta{(Counter > 0) ? 1.0f / static_cast<float>(Counter) : 0.0f};
|
||||
const auto min_len = minz(Counter, InSamples.size());
|
||||
const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size());
|
||||
const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size()) - min_len;
|
||||
for(FloatBufferLine &output : OutBuffer)
|
||||
{
|
||||
float *RESTRICT dst{al::assume_aligned<16>(output.data()+OutPos)};
|
||||
@@ -230,7 +230,7 @@ void Mix_<SSETag>(const al::span<const float> InSamples, const al::span<FloatBuf
|
||||
step_count = _mm_cvtss_f32(step_count4);
|
||||
}
|
||||
/* Mix with applying left over gain steps that aren't aligned multiples of 4. */
|
||||
for(;pos != min_len;++pos)
|
||||
for(uint_fast32_t leftover{min_len&3};leftover;++pos,--leftover)
|
||||
{
|
||||
dst[pos] += InSamples[pos] * (gain + step*step_count);
|
||||
step_count += 1.0f;
|
||||
@@ -241,7 +241,7 @@ void Mix_<SSETag>(const al::span<const float> InSamples, const al::span<FloatBuf
|
||||
gain += step*step_count;
|
||||
|
||||
/* Mix until pos is aligned with 4 or the mix is done. */
|
||||
for(;pos != aligned_len;++pos)
|
||||
for(uint_fast32_t leftover{aligned_len&3};leftover;++pos,--leftover)
|
||||
dst[pos] += InSamples[pos] * gain;
|
||||
}
|
||||
*CurrentGains = gain;
|
||||
@@ -261,7 +261,7 @@ void Mix_<SSETag>(const al::span<const float> InSamples, const al::span<FloatBuf
|
||||
pos += 4;
|
||||
} while(--todo);
|
||||
}
|
||||
for(;pos != InSamples.size();++pos)
|
||||
for(uint_fast32_t leftover{InSamples.size()&3};leftover;++pos,--leftover)
|
||||
dst[pos] += InSamples[pos] * gain;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user