IR codegen for the UpdateTuple loop. This loop is query specific and based on the aggregate functions. The function signature must match the non- codegen'd UpdateTuple exactly. For the query: select count(*), count(int_col), sum(double_col) the IR looks like: define void @UpdateTuple(%"class.impala::Aggregator"* %this_ptr, %"class.impala::AggFnEvaluator"** %agg_fn_evals, %"class.impala::Tuple"*
| 550 | // } |
| 551 | // |
| 552 | Status AggregatorConfig::CodegenUpdateTuple(LlvmCodeGen* codegen, llvm::Function** fn) { |
| 553 | for (const SlotDescriptor* slot_desc : intermediate_tuple_desc_->slots()) { |
| 554 | if (slot_desc->type().type == TYPE_CHAR) { |
| 555 | return Status::Expected("Aggregator::CodegenUpdateTuple(): cannot " |
| 556 | "codegen CHAR in aggregations"); |
| 557 | } |
| 558 | } |
| 559 | |
| 560 | if (intermediate_tuple_desc_->GetLlvmStruct(codegen) == nullptr) { |
| 561 | return Status::Expected("Aggregator::CodegenUpdateTuple(): failed to" |
| 562 | " generate intermediate tuple desc"); |
| 563 | } |
| 564 | |
| 565 | // Get the types to match the UpdateTuple signature |
| 566 | llvm::PointerType* agg_node_ptr_type = codegen->GetStructPtrType<Aggregator>(); |
| 567 | llvm::PointerType* evals_type = codegen->GetStructPtrPtrType<AggFnEvaluator>(); |
| 568 | llvm::PointerType* tuple_ptr_type = codegen->GetStructPtrType<Tuple>(); |
| 569 | llvm::PointerType* tuple_row_ptr_type = codegen->GetStructPtrType<TupleRow>(); |
| 570 | |
| 571 | llvm::StructType* tuple_struct = intermediate_tuple_desc_->GetLlvmStruct(codegen); |
| 572 | llvm::PointerType* tuple_ptr = codegen->GetPtrType(tuple_struct); |
| 573 | LlvmCodeGen::FnPrototype prototype(codegen, "UpdateTuple", codegen->void_type()); |
| 574 | prototype.AddArgument(LlvmCodeGen::NamedVariable("this_ptr", agg_node_ptr_type)); |
| 575 | prototype.AddArgument(LlvmCodeGen::NamedVariable("agg_fn_evals", evals_type)); |
| 576 | prototype.AddArgument(LlvmCodeGen::NamedVariable("tuple", tuple_ptr_type)); |
| 577 | prototype.AddArgument(LlvmCodeGen::NamedVariable("row", tuple_row_ptr_type)); |
| 578 | prototype.AddArgument(LlvmCodeGen::NamedVariable("is_merge", codegen->bool_type())); |
| 579 | |
| 580 | LlvmBuilder builder(codegen->context()); |
| 581 | llvm::Value* args[5]; |
| 582 | *fn = prototype.GeneratePrototype(&builder, &args[0]); |
| 583 | llvm::Value* agg_fn_evals_arg = args[1]; |
| 584 | llvm::Value* tuple_arg = args[2]; |
| 585 | llvm::Value* row_arg = args[3]; |
| 586 | |
| 587 | // Cast the parameter types to the internal llvm runtime types. |
| 588 | // TODO: get rid of this by using right type in function signature |
| 589 | tuple_arg = builder.CreateBitCast(tuple_arg, tuple_ptr, "tuple"); |
| 590 | |
| 591 | // Loop over each expr and generate the IR for that slot. If the expr is not |
| 592 | // count(*), generate a helper IR function to update the slot and call that. |
| 593 | int j = GetNumGroupingExprs(); |
| 594 | for (int i = 0; i < aggregate_functions_.size(); ++i, ++j) { |
| 595 | SlotDescriptor* slot_desc = intermediate_tuple_desc_->slots()[j]; |
| 596 | AggFn* agg_fn = aggregate_functions_[i]; |
| 597 | if (agg_fn->is_count_star()) { |
| 598 | // TODO: we should be able to hoist this up to the loop over the batch and just |
| 599 | // increment the slot by the number of rows in the batch. |
| 600 | int field_idx = slot_desc->llvm_field_idx(); |
| 601 | llvm::Value* const_one = codegen->GetI64Constant(1); |
| 602 | llvm::Value* slot_ptr = |
| 603 | builder.CreateStructGEP(nullptr, tuple_arg, field_idx, "src_slot"); |
| 604 | llvm::Value* slot_loaded = builder.CreateLoad(slot_ptr, "count_star_val"); |
| 605 | llvm::Value* count_inc = |
| 606 | builder.CreateAdd(slot_loaded, const_one, "count_star_inc"); |
| 607 | builder.CreateStore(count_inc, slot_ptr); |
| 608 | } else { |
| 609 | llvm::Function* update_slot_fn; |
nothing calls this directly
no test coverage detected