diff --git a/src/bits.h b/src/bits.h index de65c93..62aaf27 100644 --- a/src/bits.h +++ b/src/bits.h @@ -291,10 +291,20 @@ LC3_HOT static inline unsigned lc3_get_symbol( if (ac->low < range * symbols[s].low) { s >>= 1; +#if LC3_FAST_UDIV + /* low < range * L <=> low / range < L : one division + * instead of a dependent multiply at every probe */ + unsigned q = ac->low / range; + s -= q < symbols[s].low ? 4 : -4; + s -= q < symbols[s].low ? 2 : -2; + s -= q < symbols[s].low ? 1 : -1; + s -= q < symbols[s].low; +#else s -= ac->low < range * symbols[s].low ? 4 : -4; s -= ac->low < range * symbols[s].low ? 2 : -2; s -= ac->low < range * symbols[s].low ? 1 : -1; s -= ac->low < range * symbols[s].low; +#endif } ac->low -= range * symbols[s].low; diff --git a/src/common.h b/src/common.h index 2b23a8d..4500a3c 100644 --- a/src/common.h +++ b/src/common.h @@ -74,6 +74,21 @@ #endif /* __clang__ */ +/** + * Fast hardware unsigned division + * Set on cores where a runtime 32-bit division beats a few dependent + * multiplies (x86-64, AArch64). Unset for MCUs and audio DSPs. + */ + +#ifndef LC3_FAST_UDIV +#if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64) || defined(_M_ARM64) +#define LC3_FAST_UDIV 1 +#else +#define LC3_FAST_UDIV 0 +#endif +#endif + + /** * Macros * MIN/MAX Minimum and maximum between 2 values