Codegen for hashing the current row. In the case with both string and non-string data (group by int_col, string_col), the IR looks like: define i32 @HashRow(%"class.impala::HashTableCtx"* %this_ptr, i8* %expr_values, i8* %expr_values_null) #34 { entry: %seed = call i32 @_ZNK6impala12HashTableCtx11GetHashSeedEv( %"class.impala::HashTableCtx"* %this_ptr) %hash = call i32 @CrcHash8(i8* %expr_values
| 1024 | // ret i32 %hash_phi |
| 1025 | // } |
| 1026 | Status HashTableCtx::CodegenHashRow(LlvmCodeGen* codegen, bool use_murmur, |
| 1027 | const HashTableConfig& config, llvm::Function** fn) { |
| 1028 | const std::vector<ScalarExpr*>& exprs = config.build_exprs; |
| 1029 | const ScalarExprsResultsRowLayout& result_row_layout = |
| 1030 | config.build_exprs_results_row_layout; |
| 1031 | for (int i = 0; i < exprs.size(); ++i) { |
| 1032 | // Disable codegen for CHAR |
| 1033 | if (exprs[i]->type().type == TYPE_CHAR) { |
| 1034 | return Status("HashTableCtx::CodegenHashRow(): CHAR NYI"); |
| 1035 | } |
| 1036 | } |
| 1037 | |
| 1038 | // Get types to generate function prototype |
| 1039 | llvm::PointerType* this_ptr_type = codegen->GetStructPtrType<HashTableCtx>(); |
| 1040 | |
| 1041 | LlvmCodeGen::FnPrototype prototype( |
| 1042 | codegen, (use_murmur ? "MurmurHashRow" : "HashRow"), codegen->i32_type()); |
| 1043 | prototype.AddArgument(LlvmCodeGen::NamedVariable("this_ptr", this_ptr_type)); |
| 1044 | prototype.AddArgument(LlvmCodeGen::NamedVariable("expr_values", codegen->ptr_type())); |
| 1045 | prototype.AddArgument( |
| 1046 | LlvmCodeGen::NamedVariable("expr_values_null", codegen->ptr_type())); |
| 1047 | |
| 1048 | llvm::LLVMContext& context = codegen->context(); |
| 1049 | LlvmBuilder builder(context); |
| 1050 | llvm::Value* args[3]; |
| 1051 | *fn = prototype.GeneratePrototype(&builder, args); |
| 1052 | llvm::Value* this_arg = args[0]; |
| 1053 | llvm::Value* expr_values = args[1]; |
| 1054 | llvm::Value* expr_values_null = args[2]; |
| 1055 | |
| 1056 | // Call GetHashSeed() to get seeds_[level_] |
| 1057 | llvm::Value* seed = codegen->CodegenCallFunction( |
| 1058 | &builder, IRFunction::HASH_TABLE_GET_HASH_SEED, this_arg, "seed"); |
| 1059 | |
| 1060 | llvm::Value* hash_result = seed; |
| 1061 | const int var_result_offset = result_row_layout.var_results_begin_offset; |
| 1062 | const int expr_values_bytes_per_row = result_row_layout.expr_values_bytes_per_row; |
| 1063 | if (var_result_offset == -1) { |
| 1064 | // No variable length slots, just hash what is in 'expr_expr_values_cache_' |
| 1065 | if (expr_values_bytes_per_row > 0) { |
| 1066 | llvm::Function* hash_fn = use_murmur ? |
| 1067 | codegen->GetMurmurHashFunction(expr_values_bytes_per_row) : |
| 1068 | codegen->GetHashFunction(expr_values_bytes_per_row); |
| 1069 | llvm::Value* len = codegen->GetI32Constant(expr_values_bytes_per_row); |
| 1070 | hash_result = builder.CreateCall( |
| 1071 | hash_fn, llvm::ArrayRef<llvm::Value*>({expr_values, len, hash_result}), "hash"); |
| 1072 | } |
| 1073 | } else { |
| 1074 | if (var_result_offset > 0) { |
| 1075 | llvm::Function* hash_fn = use_murmur ? |
| 1076 | codegen->GetMurmurHashFunction(var_result_offset) : |
| 1077 | codegen->GetHashFunction(var_result_offset); |
| 1078 | llvm::Value* len = codegen->GetI32Constant(var_result_offset); |
| 1079 | hash_result = builder.CreateCall( |
| 1080 | hash_fn, llvm::ArrayRef<llvm::Value*>({expr_values, len, hash_result}), "hash"); |
| 1081 | } |
| 1082 | |
| 1083 | // Hash string slots |
nothing calls this directly
no test coverage detected