This change fixes the SaturatingMultiply<T>() function template to not cause undefined behavior with T=uint16_t.
Thanks to Richard Smith's contribution, it also no longer requires an integer division.
Patch by Richard Smith.
Differential D14845
[Support] Fix SaturatingMultiply<T>() to be correct (and fast), Re-enable Unit Tests slingn on Nov 19 2015, 3:00 PM. Authored by
Details This change fixes the SaturatingMultiply<T>() function template to not cause undefined behavior with T=uint16_t. Patch by Richard Smith.
Diff Detail Event TimelineComment Actions integer division is expensive. I wonder if we can take some fast path to by pass it T Upper = Max >> (sizeof(T)*4); return X * Y; // regular stuff Comment Actions https://llvm.org/bugs/show_bug.cgi?id=25580 Apparently not a bug with UBSan - there was a valid problem with signed integer overflow due to up-conversion of integer types with the previous implementation. Comment Actions If you have time, finding a way to speed up the method will be welcome (such as the fast path suggestion). Comment Actions See the patch I posted on the other thread for this issue -- that should Comment Actions neat - count leading zeros instructions is very fast on intel platforms. The implementation completely removed the need for idiv.
|
It'd be useful to also test cases like ((1 << A) - 1) * ((1 << B) + K), for K in [-1, 0, 1] and A + B == numeric_limits<T>::digits, as those are interesting transition cases for the new algorithm (you get overflow iff A > B and K = 1). More generally, testcases where overflow almost happens or only just happens would be good here.
Also, coverage for 0 * Max and 0 * 0 would be good.