Remove direct use of _builtin_clz.
A previous CL introduced _builtin_clz in zippy.cc. This is a GCC / Clang intrinsic, and is not supported in Visual Studio. The rest of the project uses bit manipulation intrinsics via the functions in Bits::, which are stubbed out for the open source build in zippy-stubs-internal.h. This CL extracts Bits::Log2FloorNonZero() out of Bits::Log2Floor() in the stubbed version of Bits, adds assertions to the Bits::*NonZero() functions in the stubs, and converts _builtin_clz to a Bits::Log2FloorNonZero() call. The latter part is not obvious. A mathematical proof of correctness is outlined in added comments. An empirical proof is available at https://godbolt.org/z/mPKWmh -- CalculateTableSizeOld(), which is the current code, compiles to the same assembly on Clang as CalculateTableSizeNew1(), which is the bigger jump in the proof. CalculateTableSizeNew2() is a fairly obvious transformation from CalculateTableSizeNew1(), and results in slightly better assembly on all supported compilers. Two benchmark runs with the same arguments as the original CL only showed differences in completely disjoint tests, suggesting that the differences are pure noise.
This commit is contained in:
@@ -429,7 +429,9 @@ uint32 CalculateTableSize(uint32 input_size) {
|
||||
if (input_size < 256) {
|
||||
return 256;
|
||||
}
|
||||
return 1u << (32 - __builtin_clz(input_size - 1));
|
||||
// This is equivalent to Log2Ceiling(input_size), assuming input_size > 1.
|
||||
// 2 << Log2Floor(x - 1) is equivalent to 1 << (1 + Log2Floor(x - 1)).
|
||||
return 2u << Bits::Log2Floor(input_size - 1);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in New Issue
Block a user