Constant-fold zero-initialized second CRC32 lane in CombineContiguousImpl. On 64-bit CRC32 targets, `CombineContiguousImpl` initializes the second CRC32 stream from `absl::gbswap_64(state)` even when `state` has known zero upper 32 bits (such as SwissTable's per-table seed), because LLVM does not narrow `_mm_crc32_u64`'s 64-bit initial-state operand to its low 32 bits via DemandedBits. This leaves an unnecessary data dependency from loading the table seed to the second CRC32 stream on 9–32 byte keys. Constant-fold `static_cast<uint32_t>(crcs.second)` via `__builtin_constant_p` in `CombineContiguousImpl` when known at compile time, breaking the seed-load dependency to the second CRC32 stream without adding a zero-extension when `crcs.second` is not a compile-time constant. PiperOrigin-RevId: 1008403013
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index c0d3833..37db96d 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h
@@ -1259,8 +1259,22 @@ // reading the memory. Fused instructions also reduce register pressure // allowing surrounding code to be more efficient when this code is inlined. if (len > 8) { +#if ABSL_HAVE_BUILTIN(__builtin_constant_p) + // CRC32 only uses the low 32 bits of its first argument. When `state` has + // known zero upper 32 bits in SwissTable's per-table seed, + // `static_cast<uint32_t>(crcs.second)` is a compile-time constant 0; + // folding it avoids shifting `state` and breaks the false dependency from + // loading the seed to the second CRC32 stream without adding a + // zero-extension when `crcs.second` is not a compile-time constant. + const uint64_t second_init = + __builtin_constant_p(static_cast<uint32_t>(crcs.second)) + ? static_cast<uint32_t>(crcs.second) + : crcs.second; +#else + const uint64_t second_init = crcs.second; +#endif crcs = {ABSL_HASH_INTERNAL_CRC32_U64(crcs.first, Read8(first)), - ABSL_HASH_INTERNAL_CRC32_U64(crcs.second, Read8(first + len - 8))}; + ABSL_HASH_INTERNAL_CRC32_U64(second_init, Read8(first + len - 8))}; if (len > 16) { // We compute the second round of dependent CRC32 operations. crcs = {ABSL_HASH_INTERNAL_CRC32_U64(crcs.first, Read8(first + len - 16)),