OmniSciDB  04ee39c94c
ResultSetReductionJIT Class Reference

#include <ResultSetReductionJIT.h>

+ Collaboration diagram for ResultSetReductionJIT:

Public Member Functions

 ResultSetReductionJIT (const QueryMemoryDescriptor &query_mem_desc, const std::vector< TargetInfo > &targets, const std::vector< int64_t > &target_init_vals)
 
ReductionCode codegen () const
 

Static Public Member Functions

static void clearCache ()
 

Private Member Functions

void isEmpty (const ReductionCode &reduction_code) const
 
void reduceOneEntryNoCollisions (const ReductionCode &reduction_code) const
 
void reduceOneEntryTargetsNoCollisions (const ReductionCode &reduction_code, llvm::Value *this_targets_start_ptr, llvm::Value *that_targets_start_ptr) const
 
void reduceOneEntryBaseline (const ReductionCode &reduction_code) const
 
void reduceOneEntryNoCollisionsIdx (const ReductionCode &reduction_code) const
 
void reduceOneEntryBaselineIdx (const ReductionCode &reduction_code) const
 
void reduceLoop (const ReductionCode &reduction_code) const
 
void reduceOneSlot (llvm::Value *this_ptr1, llvm::Value *this_ptr2, llvm::Value *that_ptr1, llvm::Value *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const size_t first_slot_idx_for_target, const ReductionCode &reduction_code) const
 
void reduceOneAggregateSlot (llvm::Value *this_ptr1, llvm::Value *this_ptr2, llvm::Value *that_ptr1, llvm::Value *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const int64_t init_val, const int8_t chosen_bytes, const ReductionCode &reduction_code) const
 
void reduceOneCountDistinctSlot (llvm::Value *this_ptr1, llvm::Value *that_ptr1, const size_t target_logical_idx, const ReductionCode &reduction_code) const
 
ReductionCode finalizeReductionCode (ReductionCode reduction_code) const
 
bool useInterpreter (const CgenState *cgen_state) const
 

Private Attributes

const QueryMemoryDescriptor query_mem_desc_
 
const std::vector< TargetInfotargets_
 
const std::vector< int64_t > target_init_vals_
 

Static Private Attributes

static CodeCache s_code_cache
 

Detailed Description

Definition at line 67 of file ResultSetReductionJIT.h.

Constructor & Destructor Documentation

◆ ResultSetReductionJIT()

ResultSetReductionJIT::ResultSetReductionJIT ( const QueryMemoryDescriptor query_mem_desc,
const std::vector< TargetInfo > &  targets,
const std::vector< int64_t > &  target_init_vals 
)

Definition at line 538 of file ResultSetReductionJIT.cpp.

541  : query_mem_desc_(query_mem_desc)
542  , targets_(targets)
543  , target_init_vals_(target_init_vals) {}
const std::vector< int64_t > target_init_vals_
const QueryMemoryDescriptor query_mem_desc_
const std::vector< TargetInfo > targets_

Member Function Documentation

◆ clearCache()

void ResultSetReductionJIT::clearCache ( )
static

Definition at line 603 of file ResultSetReductionJIT.cpp.

References LruCache< key_t, value_t, hash_t >::clear(), g_rt_module, and s_code_cache.

Referenced by main().

603  {
605  g_rt_module = nullptr;
606 }
void clear()
Definition: LruCache.hpp:57
std::unique_ptr< llvm::Module > g_rt_module
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ codegen()

ReductionCode ResultSetReductionJIT::codegen ( ) const

Definition at line 576 of file ResultSetReductionJIT.cpp.

References QueryMemoryDescriptor::didOutputColumnar(), logger::FATAL, finalizeReductionCode(), QueryMemoryDescriptor::getQueryDescriptionType(), GroupByBaselineHash, GroupByPerfectHash, anonymous_namespace{ResultSetReductionJIT.cpp}::is_group_query(), isEmpty(), LOG, query_mem_desc_, reduceLoop(), reduceOneEntryBaseline(), reduceOneEntryBaselineIdx(), reduceOneEntryNoCollisions(), reduceOneEntryNoCollisionsIdx(), ReductionCode::s_reduction_mutex, and anonymous_namespace{ResultSetReductionJIT.cpp}::setup_functions_ir().

Referenced by ResultSetManager::reduce(), Executor::reduceMultiDeviceResultSets(), and TEST().

576  {
577  std::lock_guard<std::mutex> reduction_guard(ReductionCode::s_reduction_mutex);
578  const auto hash_type = query_mem_desc_.getQueryDescriptionType();
579  if (query_mem_desc_.didOutputColumnar() || !is_group_query(hash_type)) {
580  return {};
581  }
582  auto reduction_code = setup_functions_ir(hash_type);
583  isEmpty(reduction_code);
586  reduceOneEntryNoCollisions(reduction_code);
587  reduceOneEntryNoCollisionsIdx(reduction_code);
588  break;
589  }
591  reduceOneEntryBaseline(reduction_code);
592  reduceOneEntryBaselineIdx(reduction_code);
593  break;
594  }
595  default: {
596  LOG(FATAL) << "Unexpected query description type";
597  }
598  }
599  reduceLoop(reduction_code);
600  return finalizeReductionCode(std::move(reduction_code));
601 }
void reduceOneEntryBaseline(const ReductionCode &reduction_code) const
void isEmpty(const ReductionCode &reduction_code) const
void reduceOneEntryNoCollisionsIdx(const ReductionCode &reduction_code) const
bool is_group_query(const QueryDescriptionType hash_type)
#define LOG(tag)
Definition: Logger.h:182
ReductionCode finalizeReductionCode(ReductionCode reduction_code) const
const QueryMemoryDescriptor query_mem_desc_
void reduceOneEntryNoCollisions(const ReductionCode &reduction_code) const
static std::mutex s_reduction_mutex
ReductionCode setup_functions_ir(const QueryDescriptionType hash_type)
void reduceOneEntryBaselineIdx(const ReductionCode &reduction_code) const
void reduceLoop(const ReductionCode &reduction_code) const
QueryDescriptionType getQueryDescriptionType() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ finalizeReductionCode()

ReductionCode ResultSetReductionJIT::finalizeReductionCode ( ReductionCode  reduction_code) const
private

Definition at line 1183 of file ResultSetReductionJIT.cpp.

References Executor::addCodeToCache(), ReductionCode::cgen_state, CPU, anonymous_namespace{ResultSetReductionJIT.cpp}::create_interpreter_engine(), ReductionCode::execution_engine, ReductionCode::func_ptr, CodeGenerator::generateNativeCPUCode(), LruCache< key_t, value_t, hash_t >::get(), ReductionCode::ir_is_empty, ReductionCode::ir_reduce_loop, ReductionCode::ir_reduce_one_entry, ReductionCode::ir_reduce_one_entry_idx, ReductionCode::module, ReductionCode::own_execution_engine, ReductionJIT, s_code_cache, serialize_llvm_object(), and useInterpreter().

Referenced by codegen().

1184  {
1185  const auto key0 = serialize_llvm_object(reduction_code.ir_is_empty);
1186  const auto key1 = serialize_llvm_object(reduction_code.ir_reduce_one_entry);
1187  const auto key2 = serialize_llvm_object(reduction_code.ir_reduce_one_entry_idx);
1188  CodeCacheKey key{key0, key1, key2};
1189  const auto val_ptr = s_code_cache.get(key);
1190  if (val_ptr) {
1191  return {
1192  nullptr,
1193  std::get<1>(val_ptr->first.front()).get(),
1194  nullptr,
1195  nullptr,
1196  nullptr,
1197  nullptr,
1198  nullptr,
1199  nullptr,
1200  reinterpret_cast<ReductionCode::FuncPtr>(std::get<0>(val_ptr->first.front()))};
1201  }
1202  CompilationOptions co{
1204  reduction_code.module.release();
1205  const bool use_interp = useInterpreter(reduction_code.cgen_state.get());
1206  auto ee = use_interp
1207  ? create_interpreter_engine(reduction_code.ir_reduce_loop)
1208  : CodeGenerator::generateNativeCPUCode(
1209  reduction_code.ir_reduce_loop, {reduction_code.ir_reduce_loop}, co);
1210  reduction_code.func_ptr =
1211  use_interp ? nullptr
1212  : reinterpret_cast<ReductionCode::FuncPtr>(
1213  ee->getPointerToFunction(reduction_code.ir_reduce_loop));
1214  reduction_code.execution_engine = ee.get();
1215  if (use_interp) {
1216  reduction_code.own_execution_engine = std::move(ee);
1217  } else {
1218  std::tuple<void*, ExecutionEngineWrapper> cache_val =
1219  std::make_tuple(reinterpret_cast<void*>(reduction_code.func_ptr), std::move(ee));
1220  std::vector<std::tuple<void*, ExecutionEngineWrapper>> cache_vals;
1221  cache_vals.emplace_back(std::move(cache_val));
1223  std::move(cache_vals),
1224  reduction_code.ir_reduce_loop->getParent(),
1225  s_code_cache);
1226  }
1227  return reduction_code;
1228 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
static void addCodeToCache(const CodeCacheKey &, std::vector< std::tuple< void *, ExecutionEngineWrapper >>, llvm::Module *, CodeCache &)
llvm::Function * ir_is_empty
std::vector< std::string > CodeCacheKey
Definition: CodeCache.h:61
int32_t(*)(int8_t *this_buff, const int8_t *that_buff, const int32_t start_entry_index, const int32_t end_entry_index, const int32_t that_entry_count, const void *this_qmd, const void *that_qmd, const void *serialized_varlen_buffer) FuncPtr
bool useInterpreter(const CgenState *cgen_state) const
llvm::Function * ir_reduce_one_entry_idx
ExecutionEngineWrapper own_execution_engine
ExecutionEngineWrapper create_interpreter_engine(llvm::Function *func)
std::string serialize_llvm_object(const T *llvm_obj)
std::unique_ptr< llvm::Module > module
llvm::Function * ir_reduce_loop
value_t * get(const key_t &key)
Definition: LruCache.hpp:39
llvm::ExecutionEngine * execution_engine
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ isEmpty()

void ResultSetReductionJIT::isEmpty ( const ReductionCode reduction_code) const
private

Definition at line 608 of file ResultSetReductionJIT.cpp.

References ReductionCode::cgen_state, CHECK, CHECK_GE, CHECK_LT, QueryMemoryDescriptor::didOutputColumnar(), anonymous_namespace{ResultSetReductionJIT.cpp}::emit_load_i32(), anonymous_namespace{ResultSetReductionJIT.cpp}::emit_load_i64(), anonymous_namespace{ResultSetReductionJIT.cpp}::emit_read_int_from_buff(), EMPTY_KEY_32, EMPTY_KEY_64, anonymous_namespace{ResultSetBaselineRadixSortTest.cpp}::empty_key_val(), logger::FATAL, get_byteoff_of_slot(), QueryMemoryDescriptor::getEffectiveKeyWidth(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::getQueryDescriptionType(), QueryMemoryDescriptor::getTargetIdxForKey(), GroupByPerfectHash, QueryMemoryDescriptor::hasKeylessHash(), ReductionCode::ir_is_empty, anonymous_namespace{ResultSetReductionJIT.cpp}::is_group_query(), LOG, query_mem_desc_, target_init_vals_, and verify_function_ir().

Referenced by codegen().

608  {
611  auto cgen_state = reduction_code.cgen_state.get();
612  auto& ctx = cgen_state->context_;
613  const auto bb_entry =
614  llvm::BasicBlock::Create(ctx, ".entry", reduction_code.ir_is_empty, 0);
615  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
616  llvm::Value* key{nullptr};
617  llvm::Value* empty_key_val{nullptr};
618  const auto arg_it = reduction_code.ir_is_empty->arg_begin();
619  const auto keys_ptr = &*arg_it;
624  CHECK_LT(static_cast<size_t>(query_mem_desc_.getTargetIdxForKey()),
625  target_init_vals_.size());
626  const auto target_slot_off =
628  const auto slot_ptr = cgen_state->ir_builder_.CreateGEP(
629  keys_ptr, cgen_state->llInt<int32_t>(target_slot_off), "is_empty_slot_ptr");
630  const auto compact_sz =
632  key = emit_read_int_from_buff(slot_ptr, compact_sz, cgen_state);
633  empty_key_val = cgen_state->llInt<int64_t>(
635  } else {
637  case 4: {
640  key = emit_load_i32(keys_ptr, cgen_state);
641  empty_key_val = cgen_state->llInt<int32_t>(EMPTY_KEY_32);
642  break;
643  }
644  case 8: {
645  key = emit_load_i64(keys_ptr, cgen_state);
646  empty_key_val = cgen_state->llInt<int64_t>(EMPTY_KEY_64);
647  break;
648  }
649  default:
650  LOG(FATAL) << "Invalid key width";
651  }
652  }
653  const auto ret =
654  cgen_state->ir_builder_.CreateICmpEQ(key, empty_key_val, "is_key_empty");
655  cgen_state->ir_builder_.CreateRet(ret);
656  verify_function_ir(reduction_code.ir_is_empty);
657 }
std::unique_ptr< CgenState > cgen_state
#define EMPTY_KEY_64
bool is_group_query(const QueryDescriptionType hash_type)
llvm::Function * ir_is_empty
#define LOG(tag)
Definition: Logger.h:182
size_t get_byteoff_of_slot(const size_t slot_idx, const QueryMemoryDescriptor &query_mem_desc)
#define CHECK_GE(x, y)
Definition: Logger.h:200
const std::vector< int64_t > target_init_vals_
const QueryMemoryDescriptor query_mem_desc_
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
llvm::Value * emit_read_int_from_buff(llvm::Value *ptr, const int8_t compact_sz, CgenState *cgen_state)
void verify_function_ir(const llvm::Function *func)
llvm::Value * emit_load_i32(llvm::Value *ptr, CgenState *cgen_state)
int32_t getTargetIdxForKey() const
#define CHECK_LT(x, y)
Definition: Logger.h:197
llvm::Value * emit_load_i64(llvm::Value *ptr, CgenState *cgen_state)
#define CHECK(condition)
Definition: Logger.h:187
#define EMPTY_KEY_32
QueryDescriptionType getQueryDescriptionType() const
size_t getEffectiveKeyWidth() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceLoop()

void ResultSetReductionJIT::reduceLoop ( const ReductionCode reduction_code) const
private

Definition at line 985 of file ResultSetReductionJIT.cpp.

References ReductionCode::cgen_state, JoinLoop::codegen(), anonymous_namespace{ResultSetReductionJIT.cpp}::generate_loop_body(), get_int_type(), INNER, ReductionCode::ir_reduce_loop, JoinLoopDomain::upper_bound, UpperBound, useInterpreter(), v(), and verify_function_ir().

Referenced by codegen().

985  {
986  const auto arg_it = reduction_code.ir_reduce_loop->arg_begin();
987  const auto this_buff_arg = &*arg_it;
988  const auto that_buff_arg = &*(arg_it + 1);
989  const auto start_index_arg = &*(arg_it + 2);
990  const auto end_index_arg = &*(arg_it + 3);
991  const auto that_entry_count_arg = &*(arg_it + 4);
992  const auto this_qmd_handle_arg = &*(arg_it + 5);
993  const auto that_qmd_handle_arg = &*(arg_it + 6);
994  const auto serialized_varlen_buffer_arg = &*(arg_it + 7);
995  auto cgen_state = reduction_code.cgen_state.get();
996  auto& ctx = cgen_state->context_;
997  const auto bb_entry =
998  llvm::BasicBlock::Create(ctx, ".entry", reduction_code.ir_reduce_loop, 0);
999  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
1000  const auto i64_type = get_int_type(64, cgen_state->context_);
1001  const auto iteration_count = cgen_state->ir_builder_.CreateSub(
1002  end_index_arg, start_index_arg, "iteration_count");
1003  const auto upper_bound = cgen_state->ir_builder_.CreateSExt(iteration_count, i64_type);
1004  const auto bb_exit =
1005  llvm::BasicBlock::Create(ctx, ".exit", reduction_code.ir_reduce_loop);
1006  cgen_state->ir_builder_.SetInsertPoint(bb_exit);
1007  cgen_state->ir_builder_.CreateRet(cgen_state->llInt<int32_t>(0));
1008  JoinLoop join_loop(
1011  [upper_bound](const std::vector<llvm::Value*>& v) {
1012  JoinLoopDomain domain{{0}};
1013  domain.upper_bound = upper_bound;
1014  return domain;
1015  },
1016  nullptr,
1017  nullptr,
1018  nullptr,
1019  "reduction_loop");
1020  const auto bb_loop_body = JoinLoop::codegen(
1021  {join_loop},
1022  [this,
1023  &reduction_code,
1024  this_buff_arg,
1025  that_buff_arg,
1026  start_index_arg,
1027  that_entry_count_arg,
1028  this_qmd_handle_arg,
1029  that_qmd_handle_arg,
1030  serialized_varlen_buffer_arg](const std::vector<llvm::Value*>& iterators) {
1031  return generate_loop_body(reduction_code,
1032  this_buff_arg,
1033  that_buff_arg,
1034  iterators.back(),
1035  start_index_arg,
1036  that_entry_count_arg,
1037  this_qmd_handle_arg,
1038  that_qmd_handle_arg,
1039  serialized_varlen_buffer_arg,
1040  !useInterpreter(reduction_code.cgen_state.get()));
1041  },
1042  nullptr,
1043  bb_exit,
1044  cgen_state->ir_builder_);
1045  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
1046  cgen_state->ir_builder_.CreateBr(bb_loop_body);
1047  verify_function_ir(reduction_code.ir_reduce_loop);
1048 }
llvm::BasicBlock * generate_loop_body(const ReductionCode &reduction_code, llvm::Value *this_buff, llvm::Value *that_buff, llvm::Value *iterator, llvm::Value *start_index, llvm::Value *that_entry_count, llvm::Value *this_qmd_handle, llvm::Value *that_qmd_handle, llvm::Value *serialized_varlen_buffer, bool emit_watchdog_check)
std::unique_ptr< CgenState > cgen_state
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
static llvm::BasicBlock * codegen(const std::vector< JoinLoop > &join_loops, const std::function< llvm::BasicBlock *(const std::vector< llvm::Value *> &)> &body_codegen, llvm::Value *outer_iter, llvm::BasicBlock *exit_bb, llvm::IRBuilder<> &builder)
Definition: JoinLoop.cpp:45
bool useInterpreter(const CgenState *cgen_state) const
void verify_function_ir(const llvm::Function *func)
T v(const TargetValue &r)
llvm::Value * upper_bound
Definition: JoinLoop.h:43
llvm::Function * ir_reduce_loop
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneAggregateSlot()

void ResultSetReductionJIT::reduceOneAggregateSlot ( llvm::Value *  this_ptr1,
llvm::Value *  this_ptr2,
llvm::Value *  that_ptr1,
llvm::Value *  that_ptr2,
const TargetInfo target_info,
const size_t  target_logical_idx,
const size_t  target_slot_idx,
const int64_t  init_val,
const int8_t  chosen_bytes,
const ReductionCode reduction_code 
) const
private

Definition at line 1109 of file ResultSetReductionJIT.cpp.

References TargetInfo::agg_kind, ReductionCode::cgen_state, CHECK_EQ, anonymous_namespace{ResultSetReductionJIT.cpp}::emit_aggregate_one_count(), anonymous_namespace{ResultSetReductionJIT.cpp}::emit_aggregate_one_nullable_value(), logger::FATAL, QueryMemoryDescriptor::getPaddedSlotWidthBytes(), is_distinct_target(), kAPPROX_COUNT_DISTINCT, kAVG, kCOUNT, kMAX, kMIN, kSUM, LOG, query_mem_desc_, and reduceOneCountDistinctSlot().

Referenced by reduceOneSlot().

1119  {
1120  const auto cgen_state = reduction_code.cgen_state.get();
1121  switch (target_info.agg_kind) {
1122  case kCOUNT:
1123  case kAPPROX_COUNT_DISTINCT: {
1124  if (is_distinct_target(target_info)) {
1125  CHECK_EQ(static_cast<size_t>(chosen_bytes), sizeof(int64_t));
1127  this_ptr1, that_ptr1, target_logical_idx, reduction_code);
1128  break;
1129  }
1130  CHECK_EQ(int64_t(0), init_val);
1131  emit_aggregate_one_count(this_ptr1, that_ptr1, chosen_bytes, cgen_state);
1132  break;
1133  }
1134  case kAVG: {
1135  // Ignore float argument compaction for count component for fear of its overflow
1136  emit_aggregate_one_count(this_ptr2,
1137  that_ptr2,
1138  query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx),
1139  cgen_state);
1140  }
1141  // fall thru
1142  case kSUM: {
1144  "sum", this_ptr1, that_ptr1, init_val, chosen_bytes, target_info, cgen_state);
1145  break;
1146  }
1147  case kMIN: {
1149  "min", this_ptr1, that_ptr1, init_val, chosen_bytes, target_info, cgen_state);
1150  break;
1151  }
1152  case kMAX: {
1154  "max", this_ptr1, that_ptr1, init_val, chosen_bytes, target_info, cgen_state);
1155  break;
1156  }
1157  default:
1158  LOG(FATAL) << "Invalid aggregate type";
1159  }
1160 }
std::unique_ptr< CgenState > cgen_state
#define CHECK_EQ(x, y)
Definition: Logger.h:195
#define LOG(tag)
Definition: Logger.h:182
void emit_aggregate_one_nullable_value(const std::string &agg_kind, llvm::Value *val_ptr, llvm::Value *other_ptr, const int64_t init_val, const size_t chosen_bytes, const TargetInfo &agg_info, CgenState *cgen_state)
const QueryMemoryDescriptor query_mem_desc_
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
Definition: sqldefs.h:71
Definition: sqldefs.h:71
bool is_distinct_target(const TargetInfo &target_info)
Definition: TargetInfo.h:116
SQLAgg agg_kind
Definition: TargetInfo.h:41
void emit_aggregate_one_count(llvm::Value *val_ptr, llvm::Value *other_ptr, const size_t chosen_bytes, CgenState *cgen_state)
Definition: sqldefs.h:71
Definition: sqldefs.h:71
Definition: sqldefs.h:71
void reduceOneCountDistinctSlot(llvm::Value *this_ptr1, llvm::Value *that_ptr1, const size_t target_logical_idx, const ReductionCode &reduction_code) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneCountDistinctSlot()

void ResultSetReductionJIT::reduceOneCountDistinctSlot ( llvm::Value *  this_ptr1,
llvm::Value *  that_ptr1,
const size_t  target_logical_idx,
const ReductionCode reduction_code 
) const
private

Definition at line 1162 of file ResultSetReductionJIT.cpp.

References ReductionCode::cgen_state, CHECK_LT, anonymous_namespace{ResultSetReductionJIT.cpp}::emit_load_i64(), QueryMemoryDescriptor::getCountDistinctDescriptorsSize(), ReductionCode::ir_reduce_one_entry, and query_mem_desc_.

Referenced by reduceOneAggregateSlot().

1166  {
1168  const auto cgen_state = reduction_code.cgen_state.get();
1169  const auto old_set_handle = emit_load_i64(this_ptr1, cgen_state);
1170  const auto new_set_handle = emit_load_i64(that_ptr1, cgen_state);
1171  const auto arg_it = reduction_code.ir_reduce_one_entry->arg_begin();
1172  const auto this_qmd_arg = &*(arg_it + 2);
1173  const auto that_qmd_arg = &*(arg_it + 3);
1174  cgen_state->emitExternalCall("count_distinct_set_union_jit_rt",
1175  llvm::Type::getVoidTy(cgen_state->context_),
1176  {new_set_handle,
1177  old_set_handle,
1178  that_qmd_arg,
1179  this_qmd_arg,
1180  cgen_state->llInt<int64_t>(target_logical_idx)});
1181 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
size_t getCountDistinctDescriptorsSize() const
const QueryMemoryDescriptor query_mem_desc_
#define CHECK_LT(x, y)
Definition: Logger.h:197
llvm::Value * emit_load_i64(llvm::Value *ptr, CgenState *cgen_state)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntryBaseline()

void ResultSetReductionJIT::reduceOneEntryBaseline ( const ReductionCode reduction_code) const
private

Definition at line 772 of file ResultSetReductionJIT.cpp.

References advance_slot(), ReductionCode::cgen_state, QueryMemoryDescriptor::getTargetGroupbyIndex(), ReductionCode::ir_reduce_one_entry, kAVG, kSAMPLE, query_mem_desc_, reduceOneSlot(), QueryMemoryDescriptor::targetGroupbyIndicesSize(), targets_, to_string(), and verify_function_ir().

Referenced by codegen().

773  {
774  auto cgen_state = reduction_code.cgen_state.get();
775  const auto bb_entry = llvm::BasicBlock::Create(
776  cgen_state->context_, ".entry", reduction_code.ir_reduce_one_entry, 0);
777  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
778  const auto arg_it = reduction_code.ir_reduce_one_entry->arg_begin();
779  const auto this_targets_ptr_arg = &*arg_it;
780  const auto that_targets_ptr_arg = &*(arg_it + 1);
781  llvm::Value* this_ptr1 = this_targets_ptr_arg;
782  llvm::Value* that_ptr1 = that_targets_ptr_arg;
783  size_t j = 0;
784  size_t init_agg_val_idx = 0;
785  for (size_t target_logical_idx = 0; target_logical_idx < targets_.size();
786  ++target_logical_idx) {
787  const auto& target_info = targets_[target_logical_idx];
788  llvm::Value* this_ptr2{nullptr};
789  llvm::Value* that_ptr2{nullptr};
790  if (target_info.is_agg &&
791  (target_info.agg_kind == kAVG ||
792  (target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen()))) {
793  const auto desc = "target_" + std::to_string(target_logical_idx) + "_second_slot";
794  const auto second_slot_rel_off = cgen_state->llInt<int32_t>(sizeof(int64_t));
795  this_ptr2 = cgen_state->ir_builder_.CreateGEP(
796  this_ptr1, second_slot_rel_off, "this_" + desc);
797  that_ptr2 = cgen_state->ir_builder_.CreateGEP(
798  that_ptr1, second_slot_rel_off, "that_" + desc);
799  }
800  reduceOneSlot(this_ptr1,
801  this_ptr2,
802  that_ptr1,
803  that_ptr2,
804  target_info,
805  target_logical_idx,
806  j,
807  init_agg_val_idx,
808  j,
809  reduction_code);
810  if (target_logical_idx + 1 == targets_.size()) {
811  break;
812  }
814  init_agg_val_idx = advance_slot(init_agg_val_idx, target_info, false);
815  } else {
816  if (query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) < 0) {
817  init_agg_val_idx = advance_slot(init_agg_val_idx, target_info, false);
818  }
819  }
820  j = advance_slot(j, target_info, false);
821  const auto next_desc =
822  "target_" + std::to_string(target_logical_idx + 1) + "_first_slot";
823  auto next_slot_rel_off =
824  cgen_state->llInt<int32_t>(init_agg_val_idx * sizeof(int64_t));
825  this_ptr1 = cgen_state->ir_builder_.CreateGEP(
826  this_targets_ptr_arg, next_slot_rel_off, next_desc);
827  that_ptr1 = cgen_state->ir_builder_.CreateGEP(
828  that_targets_ptr_arg, next_slot_rel_off, next_desc);
829  }
830  reduction_code.cgen_state->ir_builder_.CreateRetVoid();
831  verify_function_ir(reduction_code.ir_reduce_one_entry);
832 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
ssize_t getTargetGroupbyIndex(const size_t target_idx) const
const QueryMemoryDescriptor query_mem_desc_
std::string to_string(char const *&&v)
void verify_function_ir(const llvm::Function *func)
size_t advance_slot(const size_t j, const TargetInfo &target_info, const bool separate_varlen_storage)
size_t targetGroupbyIndicesSize() const
void reduceOneSlot(llvm::Value *this_ptr1, llvm::Value *this_ptr2, llvm::Value *that_ptr1, llvm::Value *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const size_t first_slot_idx_for_target, const ReductionCode &reduction_code) const
Definition: sqldefs.h:71
const std::vector< TargetInfo > targets_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntryBaselineIdx()

void ResultSetReductionJIT::reduceOneEntryBaselineIdx ( const ReductionCode reduction_code) const
private

Definition at line 867 of file ResultSetReductionJIT.cpp.

References ReductionCode::cgen_state, CHECK, QueryMemoryDescriptor::didOutputColumnar(), get_int_type(), get_row_bytes(), get_slot_off_quad(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::getQueryDescriptionType(), GroupByBaselineHash, QueryMemoryDescriptor::hasKeylessHash(), ReductionCode::ir_is_empty, ReductionCode::ir_reduce_one_entry, ReductionCode::ir_reduce_one_entry_idx, key_qw_count, query_mem_desc_, anonymous_namespace{ResultSetReductionJIT.cpp}::return_early(), and verify_function_ir().

Referenced by codegen().

868  {
873  auto cgen_state = reduction_code.cgen_state.get();
874  auto& ctx = cgen_state->context_;
875  const auto bb_entry =
876  llvm::BasicBlock::Create(ctx, ".entry", reduction_code.ir_reduce_one_entry_idx, 0);
877  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
878  const auto arg_it = reduction_code.ir_reduce_one_entry_idx->arg_begin();
879  const auto this_buff = &*arg_it;
880  const auto that_buff = &*(arg_it + 1);
881  const auto that_entry_idx = &*(arg_it + 2);
882  const auto that_entry_count = &*(arg_it + 3);
883  const auto this_qmd_handle = &*(arg_it + 4);
884  const auto that_qmd_handle = &*(arg_it + 5);
885  const auto serialized_varlen_buffer_arg = &*(arg_it + 6);
886  const auto row_bytes = cgen_state->llInt<int32_t>(get_row_bytes(query_mem_desc_));
887  const auto that_row_off_in_bytes = cgen_state->ir_builder_.CreateMul(
888  that_entry_idx, row_bytes, "that_row_off_in_bytes");
889  const auto that_row_ptr =
890  cgen_state->ir_builder_.CreateGEP(that_buff, that_row_off_in_bytes, "that_row_ptr");
891  const auto that_is_empty = cgen_state->ir_builder_.CreateCall(
892  reduction_code.ir_is_empty, that_row_ptr, "that_is_empty");
893  return_early(that_is_empty, reduction_code, reduction_code.ir_reduce_one_entry_idx, 0);
894  const auto key_count = query_mem_desc_.getGroupbyColCount();
895  const auto pi64_type = llvm::Type::getInt64PtrTy(cgen_state->context_);
896  const auto bool_type = llvm::Type::getInt8Ty(cgen_state->context_);
897  const auto this_targets_ptr_i64_ptr = cgen_state->ir_builder_.CreateAlloca(
898  pi64_type, cgen_state->llInt<int32_t>(1), "this_targets_ptr_out");
899  const auto this_is_empty_ptr = cgen_state->ir_builder_.CreateAlloca(
900  bool_type, cgen_state->llInt<int32_t>(1), "this_is_empty_out");
901  cgen_state->emitExternalCall("get_group_value_reduction_rt",
902  llvm::Type::getVoidTy(ctx),
903  {this_buff,
904  that_row_ptr,
905  cgen_state->llInt<int32_t>(key_count),
906  this_qmd_handle,
907  that_buff,
908  that_entry_idx,
909  that_entry_count,
910  row_bytes,
911  this_targets_ptr_i64_ptr,
912  this_is_empty_ptr});
913  const auto this_targets_ptr_i64 = cgen_state->ir_builder_.CreateLoad(
914  this_targets_ptr_i64_ptr, "this_targets_ptr_i64");
915  llvm::Value* this_is_empty =
916  cgen_state->ir_builder_.CreateLoad(this_is_empty_ptr, "this_is_empty");
917  this_is_empty = cgen_state->ir_builder_.CreateTrunc(
918  this_is_empty, get_int_type(1, ctx), "this_is_empty_bool");
919  return_early(this_is_empty, reduction_code, reduction_code.ir_reduce_one_entry_idx, 0);
920  const auto pi8_type = llvm::Type::getInt8PtrTy(cgen_state->context_);
922  const auto this_targets_ptr = cgen_state->ir_builder_.CreateBitCast(
923  this_targets_ptr_i64, pi8_type, "this_targets_ptr");
924  const auto key_byte_count = key_qw_count * sizeof(int64_t);
925  const auto key_byte_count_lv = cgen_state->llInt<int32_t>(key_byte_count);
926  const auto that_targets_ptr = cgen_state->ir_builder_.CreateGEP(
927  that_row_ptr, key_byte_count_lv, "that_targets_ptr");
928  cgen_state->ir_builder_.CreateCall(reduction_code.ir_reduce_one_entry,
929  {this_targets_ptr,
930  that_targets_ptr,
931  this_qmd_handle,
932  that_qmd_handle,
933  serialized_varlen_buffer_arg});
934  cgen_state->ir_builder_.CreateRetVoid();
936 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
llvm::Function * ir_is_empty
void return_early(llvm::Value *cond, const ReductionCode &reduction_code, llvm::Function *func, int error_code)
size_t get_slot_off_quad(const QueryMemoryDescriptor &query_mem_desc)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
const int64_t const uint32_t const uint32_t key_qw_count
const QueryMemoryDescriptor query_mem_desc_
void verify_function_ir(const llvm::Function *func)
llvm::Function * ir_reduce_one_entry_idx
size_t get_row_bytes(const QueryMemoryDescriptor &query_mem_desc)
#define CHECK(condition)
Definition: Logger.h:187
QueryDescriptionType getQueryDescriptionType() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntryNoCollisions()

void ResultSetReductionJIT::reduceOneEntryNoCollisions ( const ReductionCode reduction_code) const
private

Definition at line 659 of file ResultSetReductionJIT.cpp.

References align_to_int64(), ReductionCode::cgen_state, get_key_bytes_rowwise(), ReductionCode::ir_is_empty, ReductionCode::ir_reduce_one_entry, query_mem_desc_, reduceOneEntryTargetsNoCollisions(), anonymous_namespace{ResultSetReductionJIT.cpp}::return_early(), and verify_function_ir().

Referenced by codegen().

660  {
661  auto cgen_state = reduction_code.cgen_state.get();
662  const auto bb_entry = llvm::BasicBlock::Create(
663  cgen_state->context_, ".entry", reduction_code.ir_reduce_one_entry, 0);
664  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
665  const auto arg_it = reduction_code.ir_reduce_one_entry->arg_begin();
666  const auto this_row_ptr = &*arg_it;
667  const auto that_row_ptr = &*(arg_it + 1);
668  const auto that_is_empty = cgen_state->ir_builder_.CreateCall(
669  reduction_code.ir_is_empty, that_row_ptr, "that_is_empty");
670  return_early(that_is_empty, reduction_code, reduction_code.ir_reduce_one_entry, 0);
671 
672  const auto key_bytes = get_key_bytes_rowwise(query_mem_desc_);
673  if (key_bytes) { // copy the key from right hand side
674  cgen_state->ir_builder_.CreateMemCpy(
675  this_row_ptr, 0, that_row_ptr, 0, cgen_state->llInt<int32_t>(key_bytes));
676  }
677 
678  const auto key_bytes_with_padding = align_to_int64(key_bytes);
679  const auto key_bytes_lv = cgen_state->llInt<int32_t>(key_bytes_with_padding);
680  const auto this_targets_start_ptr =
681  cgen_state->ir_builder_.CreateGEP(this_row_ptr, key_bytes_lv, "this_targets_start");
682  const auto that_targets_start_ptr =
683  cgen_state->ir_builder_.CreateGEP(that_row_ptr, key_bytes_lv, "that_targets_start");
684 
686  reduction_code, this_targets_start_ptr, that_targets_start_ptr);
687  verify_function_ir(reduction_code.ir_reduce_one_entry);
688 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
llvm::Function * ir_is_empty
void return_early(llvm::Value *cond, const ReductionCode &reduction_code, llvm::Function *func, int error_code)
const QueryMemoryDescriptor query_mem_desc_
void verify_function_ir(const llvm::Function *func)
size_t get_key_bytes_rowwise(const QueryMemoryDescriptor &query_mem_desc)
FORCE_INLINE HOST DEVICE T align_to_int64(T addr)
void reduceOneEntryTargetsNoCollisions(const ReductionCode &reduction_code, llvm::Value *this_targets_start_ptr, llvm::Value *that_targets_start_ptr) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntryNoCollisionsIdx()

void ResultSetReductionJIT::reduceOneEntryNoCollisionsIdx ( const ReductionCode reduction_code) const
private

Definition at line 834 of file ResultSetReductionJIT.cpp.

References ReductionCode::cgen_state, CHECK, get_row_bytes(), QueryMemoryDescriptor::getQueryDescriptionType(), GroupByPerfectHash, ReductionCode::ir_reduce_one_entry, ReductionCode::ir_reduce_one_entry_idx, query_mem_desc_, and verify_function_ir().

Referenced by codegen().

835  {
838  auto cgen_state = reduction_code.cgen_state.get();
839  auto& ctx = cgen_state->context_;
840  const auto bb_entry =
841  llvm::BasicBlock::Create(ctx, ".entry", reduction_code.ir_reduce_one_entry_idx, 0);
842  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
843  const auto arg_it = reduction_code.ir_reduce_one_entry_idx->arg_begin();
844  const auto this_buff = &*arg_it;
845  const auto that_buff = &*(arg_it + 1);
846  const auto entry_idx = &*(arg_it + 2);
847  const auto this_qmd_handle = &*(arg_it + 4);
848  const auto that_qmd_handle = &*(arg_it + 5);
849  const auto serialized_varlen_buffer_arg = &*(arg_it + 6);
850  const auto row_bytes = cgen_state->llInt<int32_t>(get_row_bytes(query_mem_desc_));
851  const auto row_off_in_bytes =
852  cgen_state->ir_builder_.CreateMul(entry_idx, row_bytes, "row_off_in_bytes");
853  const auto this_row_ptr =
854  cgen_state->ir_builder_.CreateGEP(this_buff, row_off_in_bytes, "this_row_ptr");
855  const auto that_row_ptr =
856  cgen_state->ir_builder_.CreateGEP(that_buff, row_off_in_bytes, "that_row_ptr");
857  cgen_state->ir_builder_.CreateCall(reduction_code.ir_reduce_one_entry,
858  {this_row_ptr,
859  that_row_ptr,
860  this_qmd_handle,
861  that_qmd_handle,
862  serialized_varlen_buffer_arg});
863  cgen_state->ir_builder_.CreateRetVoid();
865 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
const QueryMemoryDescriptor query_mem_desc_
void verify_function_ir(const llvm::Function *func)
llvm::Function * ir_reduce_one_entry_idx
size_t get_row_bytes(const QueryMemoryDescriptor &query_mem_desc)
#define CHECK(condition)
Definition: Logger.h:187
QueryDescriptionType getQueryDescriptionType() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntryTargetsNoCollisions()

void ResultSetReductionJIT::reduceOneEntryTargetsNoCollisions ( const ReductionCode reduction_code,
llvm::Value *  this_targets_start_ptr,
llvm::Value *  that_targets_start_ptr 
) const
private

Definition at line 690 of file ResultSetReductionJIT.cpp.

References ReductionCode::cgen_state, QueryMemoryDescriptor::getColSlotContext(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::getTargetGroupbyIndex(), ReductionCode::ir_reduce_one_entry, kAVG, kSAMPLE, query_mem_desc_, reduceOneSlot(), QueryMemoryDescriptor::targetGroupbyIndicesSize(), targets_, to_string(), UNLIKELY, and verify_function_ir().

Referenced by reduceOneEntryNoCollisions().

693  {
694  auto cgen_state = reduction_code.cgen_state.get();
695  const auto& col_slot_context = query_mem_desc_.getColSlotContext();
696  llvm::Value* this_targets_ptr = this_targets_start_ptr;
697  llvm::Value* that_targets_ptr = that_targets_start_ptr;
698  size_t init_agg_val_idx = 0;
699  for (size_t target_logical_idx = 0; target_logical_idx < targets_.size();
700  ++target_logical_idx) {
701  const auto& target_info = targets_[target_logical_idx];
702  const auto& slots_for_col = col_slot_context.getSlotsForCol(target_logical_idx);
703  llvm::Value* this_ptr2{nullptr};
704  llvm::Value* that_ptr2{nullptr};
705 
706  bool two_slot_target{false};
707  if (target_info.is_agg &&
708  (target_info.agg_kind == kAVG ||
709  (target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen()))) {
710  // Note that this assumes if one of the slot pairs in a given target is an array,
711  // all slot pairs are arrays. Currently this is true for all geo targets, but we
712  // should better codify and store this information in the future
713  two_slot_target = true;
714  }
715 
716  for (size_t target_slot_idx = slots_for_col.front();
717  target_slot_idx < slots_for_col.back() + 1;
718  target_slot_idx += 2) {
719  const auto slot_off_val = query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx);
720  const auto slot_off = cgen_state->llInt<int32_t>(slot_off_val);
721  if (UNLIKELY(two_slot_target)) {
722  const auto desc = "target_" + std::to_string(target_logical_idx) + "_second_slot";
723  this_ptr2 =
724  cgen_state->ir_builder_.CreateGEP(this_targets_ptr, slot_off, "this_" + desc);
725  that_ptr2 =
726  cgen_state->ir_builder_.CreateGEP(that_targets_ptr, slot_off, "that_" + desc);
727  }
728  reduceOneSlot(this_targets_ptr,
729  this_ptr2,
730  that_targets_ptr,
731  that_ptr2,
732  target_info,
733  target_logical_idx,
734  target_slot_idx,
735  init_agg_val_idx,
736  slots_for_col.front(),
737  reduction_code);
738  auto increment_agg_val_idx_maybe =
739  [&init_agg_val_idx, &target_logical_idx, this](const int slot_count) {
741  query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) < 0) {
742  init_agg_val_idx += slot_count;
743  }
744  };
745  if (target_logical_idx + 1 == targets_.size() &&
746  target_slot_idx + 1 >= slots_for_col.back()) {
747  break;
748  }
749  const auto next_desc =
750  "target_" + std::to_string(target_logical_idx + 1) + "_first_slot";
751  if (UNLIKELY(two_slot_target)) {
752  increment_agg_val_idx_maybe(2);
753  const auto two_slot_off = cgen_state->llInt<int32_t>(
754  slot_off_val + query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx + 1));
755  this_targets_ptr = cgen_state->ir_builder_.CreateGEP(
756  this_targets_ptr, two_slot_off, "this_" + next_desc);
757  that_targets_ptr = cgen_state->ir_builder_.CreateGEP(
758  that_targets_ptr, two_slot_off, "that_" + next_desc);
759  } else {
760  increment_agg_val_idx_maybe(1);
761  this_targets_ptr = cgen_state->ir_builder_.CreateGEP(
762  this_targets_ptr, slot_off, "this_" + next_desc);
763  that_targets_ptr = cgen_state->ir_builder_.CreateGEP(
764  that_targets_ptr, slot_off, "that_" + next_desc);
765  }
766  }
767  }
768  reduction_code.cgen_state->ir_builder_.CreateRetVoid();
769  verify_function_ir(reduction_code.ir_reduce_one_entry);
770 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
ssize_t getTargetGroupbyIndex(const size_t target_idx) const
const QueryMemoryDescriptor query_mem_desc_
std::string to_string(char const *&&v)
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
void verify_function_ir(const llvm::Function *func)
size_t targetGroupbyIndicesSize() const
#define UNLIKELY(x)
Definition: likely.h:20
const ColSlotContext & getColSlotContext() const
void reduceOneSlot(llvm::Value *this_ptr1, llvm::Value *this_ptr2, llvm::Value *that_ptr1, llvm::Value *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const size_t first_slot_idx_for_target, const ReductionCode &reduction_code) const
Definition: sqldefs.h:71
const std::vector< TargetInfo > targets_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneSlot()

void ResultSetReductionJIT::reduceOneSlot ( llvm::Value *  this_ptr1,
llvm::Value *  this_ptr2,
llvm::Value *  that_ptr1,
llvm::Value *  that_ptr2,
const TargetInfo target_info,
const size_t  target_logical_idx,
const size_t  target_slot_idx,
const size_t  init_agg_val_idx,
const size_t  first_slot_idx_for_target,
const ReductionCode reduction_code 
) const
private

Definition at line 1050 of file ResultSetReductionJIT.cpp.

References TargetInfo::agg_kind, ReductionCode::cgen_state, CHECK, CHECK_LT, anonymous_namespace{ResultSetReductionJIT.cpp}::emit_write_projection(), SQLTypeInfoCore< TYPE_FACET_PACK >::get_elem_type(), get_width_for_slot(), QueryMemoryDescriptor::getTargetGroupbyIndex(), ReductionCode::ir_reduce_one_entry, TargetInfo::is_agg, SQLTypeInfoCore< TYPE_FACET_PACK >::is_geometry(), SQLTypeInfoCore< TYPE_FACET_PACK >::is_string(), SQLTypeInfoCore< TYPE_FACET_PACK >::is_varlen(), kSAMPLE, query_mem_desc_, reduceOneAggregateSlot(), TargetInfo::sql_type, takes_float_argument(), target_init_vals_, and QueryMemoryDescriptor::targetGroupbyIndicesSize().

Referenced by reduceOneEntryBaseline(), and reduceOneEntryTargetsNoCollisions().

1059  {
1061  if (query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) >= 0) {
1062  return;
1063  }
1064  }
1065  const bool float_argument_input = takes_float_argument(target_info);
1066  const auto chosen_bytes =
1067  get_width_for_slot(target_slot_idx, float_argument_input, query_mem_desc_);
1068  CHECK_LT(init_agg_val_idx, target_init_vals_.size());
1069  auto init_val = target_init_vals_[init_agg_val_idx];
1070  if (target_info.is_agg && target_info.agg_kind != kSAMPLE) {
1071  reduceOneAggregateSlot(this_ptr1,
1072  this_ptr2,
1073  that_ptr1,
1074  that_ptr2,
1075  target_info,
1076  target_logical_idx,
1077  target_slot_idx,
1078  init_val,
1079  chosen_bytes,
1080  reduction_code);
1081  } else {
1082  const auto cgen_state = reduction_code.cgen_state.get();
1083  emit_write_projection(this_ptr1, that_ptr1, init_val, chosen_bytes, cgen_state);
1084  if (target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen()) {
1085  CHECK(this_ptr2 && that_ptr2);
1086  size_t length_to_elems{0};
1087  if (target_info.sql_type.is_geometry()) {
1088  // TODO: Assumes hard-coded sizes for geometry targets
1089  length_to_elems = target_slot_idx == first_slot_idx_for_target ? 1 : 4;
1090  } else {
1091  const auto& elem_ti = target_info.sql_type.get_elem_type();
1092  length_to_elems = target_info.sql_type.is_string() ? 1 : elem_ti.get_size();
1093  }
1094  const auto arg_it = reduction_code.ir_reduce_one_entry->arg_begin();
1095  const auto serialized_varlen_buffer_arg = &*(arg_it + 4);
1096  cgen_state->emitExternalCall("serialized_varlen_buffer_sample",
1097  llvm::Type::getVoidTy(cgen_state->context_),
1098  {serialized_varlen_buffer_arg,
1099  this_ptr1,
1100  this_ptr2,
1101  that_ptr1,
1102  that_ptr2,
1103  cgen_state->llInt<int64_t>(init_val),
1104  cgen_state->llInt<int64_t>(length_to_elems)});
1105  }
1106  }
1107 }
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
ssize_t getTargetGroupbyIndex(const size_t target_idx) const
SQLTypeInfo sql_type
Definition: TargetInfo.h:42
bool is_varlen() const
Definition: sqltypes.h:464
const std::vector< int64_t > target_init_vals_
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:120
int8_t get_width_for_slot(const size_t target_slot_idx, const bool float_argument_input, const QueryMemoryDescriptor &query_mem_desc)
const QueryMemoryDescriptor query_mem_desc_
bool is_agg
Definition: TargetInfo.h:40
SQLTypeInfoCore get_elem_type() const
Definition: sqltypes.h:632
size_t targetGroupbyIndicesSize() const
SQLAgg agg_kind
Definition: TargetInfo.h:41
#define CHECK_LT(x, y)
Definition: Logger.h:197
void reduceOneAggregateSlot(llvm::Value *this_ptr1, llvm::Value *this_ptr2, llvm::Value *that_ptr1, llvm::Value *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const int64_t init_val, const int8_t chosen_bytes, const ReductionCode &reduction_code) const
#define CHECK(condition)
Definition: Logger.h:187
bool is_geometry() const
Definition: sqltypes.h:462
bool is_string() const
Definition: sqltypes.h:450
void emit_write_projection(llvm::Value *slot_pi8, llvm::Value *other_pi8, const int64_t init_val, const size_t chosen_bytes, CgenState *cgen_state)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ useInterpreter()

bool ResultSetReductionJIT::useInterpreter ( const CgenState cgen_state) const
private

Definition at line 1230 of file ResultSetReductionJIT.cpp.

References QueryMemoryDescriptor::getEntryCount(), CgenState::has_external_calls_, anonymous_namespace{ResultSetReductionJIT.cpp}::INTERP_THRESHOLD, and query_mem_desc_.

Referenced by finalizeReductionCode(), and reduceLoop().

1230  {
1231  // The LLVM interpreter uses llvm::Function* pointers as keys in a cache to quickly
1232  // resolve binding to external functions. That works if the functions are kept around
1233  // for the entire lifetime of the process. Unfortunately, that is incompatible with our
1234  // need to free functions and modules, because the pointers could be recycled and lead
1235  // to false hits in that cache.
1237  !cgen_state->has_external_calls_;
1238 }
bool has_external_calls_
Definition: CgenState.h:285
const QueryMemoryDescriptor query_mem_desc_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ query_mem_desc_

◆ s_code_cache

CodeCache ResultSetReductionJIT::s_code_cache
staticprivate

Definition at line 142 of file ResultSetReductionJIT.h.

Referenced by clearCache(), and finalizeReductionCode().

◆ target_init_vals_

const std::vector<int64_t> ResultSetReductionJIT::target_init_vals_
private

Definition at line 141 of file ResultSetReductionJIT.h.

Referenced by isEmpty(), and reduceOneSlot().

◆ targets_

const std::vector<TargetInfo> ResultSetReductionJIT::targets_
private

The documentation for this class was generated from the following files: