MCPcopy Create free account
hub / github.com/apache/impala / GetHashFunction

Method GetHashFunction

be/src/codegen/llvm-codegen.cc:1850–1962  ·  view source on GitHub ↗

Codegen to compute hash for a particular byte size. Loops are unrolled in this process. For the case where num_bytes == 11, we'd do this by calling 1. crc64 (for first 8 bytes) 2. crc16 (for bytes 9, 10) 3. crc8 (for byte 11) The resulting IR looks like: define i32 @CrcHash11(i8* %data, i32 %len, i32 %seed) { entry: %0 = zext i32 %seed to i64 %1 = bitcast i8* %data to i64 %2 = getelementptr i64*

Source from the content-addressed store, hash-verified

1848// ret i32 %12
1849// }
1850llvm::Function* LlvmCodeGen::GetHashFunction(int num_bytes) {
1851 if (IS_AARCH64 || IsCPUFeatureEnabled(CpuInfo::SSE4_2)) {
1852 if (num_bytes == -1) {
1853 // -1 indicates variable length, just return the generic loop based
1854 // hash fn.
1855 return GetFunction(IRFunction::HASH_CRC, false);
1856 }
1857
1858 map<int, llvm::Function*>::iterator cached_fn = hash_fns_.find(num_bytes);
1859 if (cached_fn != hash_fns_.end()) {
1860 return cached_fn->second;
1861 }
1862
1863 // Generate a function to hash these bytes
1864 stringstream ss;
1865 ss << "CrcHash" << num_bytes;
1866 FnPrototype prototype(this, ss.str(), i32_type());
1867 prototype.AddArgument(LlvmCodeGen::NamedVariable("data", ptr_type()));
1868 prototype.AddArgument(LlvmCodeGen::NamedVariable("len", i32_type()));
1869 prototype.AddArgument(LlvmCodeGen::NamedVariable("seed", i32_type()));
1870
1871 llvm::Value* args[3];
1872 LlvmBuilder builder(context());
1873 llvm::Function* fn = prototype.GeneratePrototype(&builder, &args[0]);
1874 llvm::Value* data = args[0];
1875 llvm::Value* result = args[2];
1876#ifdef __aarch64__
1877 llvm::Function* crc8_fn = llvm_intrinsics_[llvm::Intrinsic::aarch64_crc32cb];
1878 llvm::Function* crc16_fn = llvm_intrinsics_[llvm::Intrinsic::aarch64_crc32ch];
1879 llvm::Function* crc32_fn = llvm_intrinsics_[llvm::Intrinsic::aarch64_crc32cw];
1880 llvm::Function* crc64_fn = llvm_intrinsics_[llvm::Intrinsic::aarch64_crc32cx];
1881#else
1882 llvm::Function* crc8_fn = llvm_intrinsics_[llvm::Intrinsic::x86_sse42_crc32_32_8];
1883 llvm::Function* crc16_fn = llvm_intrinsics_[llvm::Intrinsic::x86_sse42_crc32_32_16];
1884 llvm::Function* crc32_fn = llvm_intrinsics_[llvm::Intrinsic::x86_sse42_crc32_32_32];
1885 llvm::Function* crc64_fn = llvm_intrinsics_[llvm::Intrinsic::x86_sse42_crc32_64_64];
1886#endif
1887
1888 // Generate the crc instructions starting with the highest number of bytes
1889 if (num_bytes >= 8) {
1890#ifndef __aarch64__
1891 llvm::Value* result_64 = builder.CreateZExt(result, i64_type());
1892#endif
1893 llvm::Value* ptr = builder.CreateBitCast(data, i64_ptr_type());
1894 int i = 0;
1895 while (num_bytes >= 8) {
1896 llvm::Value* index[] = {GetI32Constant(i++)};
1897 llvm::Value* d = builder.CreateLoad(builder.CreateInBoundsGEP(ptr, index));
1898#ifdef __aarch64__
1899 result = builder.CreateCall(crc64_fn, llvm::ArrayRef<llvm::Value*>({result, d}));
1900#else
1901 result_64 =
1902 builder.CreateCall(crc64_fn, llvm::ArrayRef<llvm::Value*>({result_64, d}));
1903#endif
1904 num_bytes -= 8;
1905 }
1906#ifndef __aarch64__
1907 result = builder.CreateTrunc(result_64, i32_type());

Callers 3

CodegenHashRowMethod · 0.80
TEST_FFunction · 0.80
CodegenCrcHashFunction · 0.80

Calls 7

NamedVariableClass · 0.85
AddArgumentMethod · 0.80
GeneratePrototypeMethod · 0.80
CreateCallMethod · 0.80
findMethod · 0.45
endMethod · 0.45
strMethod · 0.45

Tested by 1

TEST_FFunction · 0.64