OmniSciDB  cde582ebc3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TableFunctionCompilationContext Class Reference

#include <TableFunctionCompilationContext.h>

+ Collaboration diagram for TableFunctionCompilationContext:

Public Member Functions

 TableFunctionCompilationContext (Executor *executor, const CompilationOptions &co)
 
 TableFunctionCompilationContext (const TableFunctionCompilationContext &)=delete
 
TableFunctionCompilationContextoperator= (const TableFunctionCompilationContext &)=delete
 
std::shared_ptr
< CompilationContext
compile (const TableFunctionExecutionUnit &exe_unit, bool emit_only_preflight_fn)
 

Private Member Functions

void generateEntryPoint (const TableFunctionExecutionUnit &exe_unit, bool emit_only_preflight_fn)
 
void generateTableFunctionCall (const TableFunctionExecutionUnit &exe_unit, const std::vector< llvm::Value * > &func_args, llvm::BasicBlock *bb_exit, llvm::Value *output_row_count_ptr, bool emit_only_preflight_fn)
 
void generateCastsForInputTypes (const TableFunctionExecutionUnit &exe_unit, const std::vector< std::pair< llvm::Value *, const SQLTypeInfo >> &columns_to_cast, llvm::Value *mgr_ptr)
 
void generateGpuKernel ()
 
bool passColumnsByValue (const TableFunctionExecutionUnit &exe_unit)
 
std::shared_ptr
< CompilationContext
finalize (bool emit_only_preflight_fn)
 

Private Attributes

llvm::Function * entry_point_func_
 
llvm::Function * kernel_func_
 
Executorexecutor_
 
const CompilationOptionsco_
 

Detailed Description

Definition at line 29 of file TableFunctionCompilationContext.h.

Constructor & Destructor Documentation

TableFunctionCompilationContext::TableFunctionCompilationContext ( Executor executor,
const CompilationOptions co 
)
inline

Definition at line 31 of file TableFunctionCompilationContext.h.

TableFunctionCompilationContext::TableFunctionCompilationContext ( const TableFunctionCompilationContext )
delete

Member Function Documentation

std::shared_ptr< CompilationContext > TableFunctionCompilationContext::compile ( const TableFunctionExecutionUnit exe_unit,
bool  emit_only_preflight_fn 
)

Definition at line 428 of file TableFunctionCompilationContext.cpp.

References CHECK, co_, DEBUG_TIMER, CompilationOptions::device_type, entry_point_func_, executor_, anonymous_namespace{TableFunctionCompilationContext.cpp}::exprsKey(), finalize(), anonymous_namespace{TableFunctionCompilationContext.cpp}::generate_entry_point(), generateEntryPoint(), generateGpuKernel(), QueryEngine::getInstance(), table_functions::TableFunction::getName(), GPU, TableFunctionExecutionUnit::input_exprs, TableFunctionExecutionUnit::table_func, TableFunctionExecutionUnit::target_exprs, and to_string().

Referenced by Executor::executeTableFunction().

430  {
431  auto timer = DEBUG_TIMER(__func__);
432 
433  // Here we assume that Executor::tf_code_accessor is cleared when a
434  // UDTF implementation is changed. TODO: Ideally, the key should
435  // contain a hash of an UDTF implementation string. This could be
436  // achieved by including the hash value to the prefix of the UDTF
437  // name, for instance.
438  CodeCacheKey key{exe_unit.table_func.getName(),
439  exprsKey(exe_unit.input_exprs),
440  exprsKey(exe_unit.target_exprs),
441  std::to_string(emit_only_preflight_fn),
443 
444  auto cached_code = QueryEngine::getInstance()->tf_code_accessor->get_or_wait(key);
445  if (cached_code) {
446  return *cached_code;
447  }
448 
449  auto cgen_state = executor_->getCgenStatePtr();
450  CHECK(cgen_state);
451  CHECK(cgen_state->module_ == nullptr);
452  cgen_state->set_module_shallow_copy(executor_->get_rt_module());
453 
455 
456  generateEntryPoint(exe_unit, emit_only_preflight_fn);
457 
459  CHECK(!emit_only_preflight_fn);
461  }
462 
463  QueryEngine::getInstance()->tf_code_accessor->swap(key,
464  finalize(emit_only_preflight_fn));
465  return QueryEngine::getInstance()->tf_code_accessor->get_value(key);
466 }
std::string exprsKey(const std::vector< Analyzer::Expr * > &exprs)
void generateEntryPoint(const TableFunctionExecutionUnit &exe_unit, bool emit_only_preflight_fn)
std::vector< Analyzer::Expr * > input_exprs
const table_functions::TableFunction table_func
llvm::Function * generate_entry_point(const CgenState *cgen_state)
std::shared_ptr< CompilationContext > finalize(bool emit_only_preflight_fn)
std::vector< std::string > CodeCacheKey
Definition: CodeCache.h:25
std::string to_string(char const *&&v)
std::string getName(const bool drop_suffix=false, const bool lower=false) const
ExecutorDeviceType device_type
#define CHECK(condition)
Definition: Logger.h:222
#define DEBUG_TIMER(name)
Definition: Logger.h:371
static std::shared_ptr< QueryEngine > getInstance()
Definition: QueryEngine.h:81
std::vector< Analyzer::Expr * > target_exprs

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< CompilationContext > TableFunctionCompilationContext::finalize ( bool  emit_only_preflight_fn)
private

Definition at line 875 of file TableFunctionCompilationContext.cpp.

References CHECK, co_, DEBUG_TIMER, CompilationOptions::device_type, entry_point_func_, executor_, CodeGenerator::generateNativeCPUCode(), CodeGenerator::generateNativeGPUCode(), GPU, logger::IR, kernel_func_, CodeGenerator::link_udf_module(), LOG, and serialize_llvm_object().

Referenced by compile().

876  {
877  auto timer = DEBUG_TIMER(__func__);
878  /*
879  TODO 1: eliminate need for OverrideFromSrc
880  TODO 2: detect and link only the udf's that are needed
881  */
882  auto cgen_state = executor_->getCgenStatePtr();
883  auto is_gpu = co_.device_type == ExecutorDeviceType::GPU;
884  if (executor_->has_rt_udf_module(is_gpu)) {
885  CodeGenerator::link_udf_module(executor_->get_rt_udf_module(is_gpu),
886  *(cgen_state->module_),
887  cgen_state,
888  llvm::Linker::Flags::OverrideFromSrc);
889  }
890 
891  LOG(IR) << (emit_only_preflight_fn ? "Pre Flight Function Entry Point IR\n"
892  : "Table Function Entry Point IR\n")
894  std::shared_ptr<CompilationContext> code;
895  if (is_gpu) {
896  LOG(IR) << "Table Function Kernel IR\n" << serialize_llvm_object(kernel_func_);
897 
898  CHECK(executor_);
899  executor_->initializeNVPTXBackend();
900 
901  CodeGenerator::GPUTarget gpu_target{executor_->nvptx_target_machine_.get(),
902  executor_->cudaMgr(),
903  executor_->blockSize(),
904  cgen_state,
905  false};
908  kernel_func_,
910  /*is_gpu_smem_used=*/false,
911  co_,
912  gpu_target);
913  } else {
914  auto ee =
916  auto cpu_code = std::make_shared<CpuCompilationContext>(std::move(ee));
917  cpu_code->setFunctionPointer(entry_point_func_);
918  code = cpu_code;
919  }
920  LOG(IR) << "End of IR";
921 
922  return code;
923 }
#define LOG(tag)
Definition: Logger.h:216
static ExecutionEngineWrapper generateNativeCPUCode(llvm::Function *func, const std::unordered_set< llvm::Function * > &live_funcs, const CompilationOptions &co)
static void link_udf_module(const std::unique_ptr< llvm::Module > &udf_module, llvm::Module &module, CgenState *cgen_state, llvm::Linker::Flags flags=llvm::Linker::Flags::None)
ExecutorDeviceType device_type
std::string serialize_llvm_object(const T *llvm_obj)
static std::shared_ptr< GpuCompilationContext > generateNativeGPUCode(Executor *executor, llvm::Function *func, llvm::Function *wrapper_func, const std::unordered_set< llvm::Function * > &live_funcs, const bool is_gpu_smem_used, const CompilationOptions &co, const GPUTarget &gpu_target)
#define CHECK(condition)
Definition: Logger.h:222
#define DEBUG_TIMER(name)
Definition: Logger.h:371

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateCastsForInputTypes ( const TableFunctionExecutionUnit exe_unit,
const std::vector< std::pair< llvm::Value *, const SQLTypeInfo >> &  columns_to_cast,
llvm::Value *  mgr_ptr 
)
private

Definition at line 753 of file TableFunctionCompilationContext.cpp.

References anonymous_namespace{TableFunctionCompilationContext.cpp}::cast_column(), co_, CompilationOptions::device_type, entry_point_func_, executor_, GPU, kTIMESTAMP, TableFunctionExecutionUnit::table_func, to_string(), and table_functions::TableFunction::usesManager().

Referenced by generateEntryPoint().

756  {
757  auto* cgen_state = executor_->getCgenStatePtr();
758  llvm::LLVMContext& ctx = cgen_state->context_;
759  llvm::IRBuilder<>* ir_builder = &cgen_state->ir_builder_;
760  CodeGenerator codeGenerator = CodeGenerator(cgen_state, executor_->getPlanStatePtr());
761  llvm::Function* old_func = cgen_state->current_func_;
762  cgen_state->current_func_ =
763  entry_point_func_; // update cgen_state current func for CodeGenerator
764 
765  for (unsigned i = 0; i < columns_to_cast.size(); ++i) {
766  auto [col_ptr, ti] = columns_to_cast[i];
767 
768  if (ti.is_column() && ti.get_subtype() == kTIMESTAMP && ti.get_precision() != 9) {
769  // TIMESTAMP columns should always have nanosecond precision
770  SQLTypeInfo orig_ti = SQLTypeInfo(
771  ti.get_subtype(), ti.get_precision(), ti.get_dimension(), ti.get_notnull());
772  SQLTypeInfo dest_ti =
773  SQLTypeInfo(kTIMESTAMP, 9, ti.get_dimension(), ti.get_notnull());
774  cast_column(col_ptr,
776  orig_ti,
777  dest_ti,
778  std::to_string(i + 1),
779  *ir_builder,
780  ctx,
781  codeGenerator);
782  }
783  }
784 
785  // The QueryEngine CodeGenerator will codegen return values corresponding to
786  // QueryExecutionError codes. Since at the table function level we'd like error handling
787  // to be done by the TableFunctionManager, we replace the codegen'd returns by calls to
788  // the appropriate Manager functions.
790  // TableFunctionManager is not supported on GPU, so leave the QueryExecutionError code
791  return;
792  }
793 
794  std::vector<llvm::ReturnInst*> rets_to_replace;
795  for (llvm::BasicBlock& BB : *entry_point_func_) {
796  for (llvm::Instruction& I : BB) {
797  if (!llvm::isa<llvm::ReturnInst>(&I)) {
798  continue;
799  }
800  llvm::ReturnInst* RI = llvm::cast<llvm::ReturnInst>(&I);
801  llvm::Value* retValue = RI->getReturnValue();
802  if (!retValue || !llvm::isa<llvm::ConstantInt>(retValue)) {
803  continue;
804  }
805  llvm::ConstantInt* retConst = llvm::cast<llvm::ConstantInt>(retValue);
806  if (retConst->getValue() == 7) {
807  // ret 7 = underflow/overflow during casting attempt
808  rets_to_replace.push_back(RI);
809  }
810  }
811  }
812 
813  auto prev_insert_point = ir_builder->saveIP();
814  for (llvm::ReturnInst* RI : rets_to_replace) {
815  ir_builder->SetInsertPoint(RI);
816  llvm::Value* err_msg = ir_builder->CreateGlobalStringPtr(
817  "Underflow or overflow during casting of input types!", "cast_err_str");
818  llvm::Value* error_call;
819  if (exe_unit.table_func.usesManager()) {
820  error_call = cgen_state->emitExternalCall("TableFunctionManager_error_message",
821  ir_builder->getInt32Ty(),
822  {mgr_ptr, err_msg});
823  } else {
824  error_call = cgen_state->emitExternalCall(
825  "table_function_error", ir_builder->getInt32Ty(), {err_msg});
826  }
827  llvm::ReplaceInstWithInst(RI, llvm::ReturnInst::Create(ctx, error_call));
828  }
829  ir_builder->restoreIP(prev_insert_point);
830 
831  cgen_state->current_func_ = old_func;
832 }
const table_functions::TableFunction table_func
std::string to_string(char const *&&v)
ExecutorDeviceType device_type
void cast_column(llvm::Value *col_base_ptr, llvm::Function *func, SQLTypeInfo &orig_ti, SQLTypeInfo &dest_ti, std::string index, llvm::IRBuilder<> &ir_builder, llvm::LLVMContext &ctx, CodeGenerator &codeGenerator)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateEntryPoint ( const TableFunctionExecutionUnit exe_unit,
bool  emit_only_preflight_fn 
)
private

Definition at line 524 of file TableFunctionCompilationContext.cpp.

References anonymous_namespace{TableFunctionCompilationContext.cpp}::alloc_column(), anonymous_namespace{TableFunctionCompilationContext.cpp}::alloc_column_list(), CHECK, CHECK_EQ, co_, anonymous_namespace{TableFunctionCompilationContext.cpp}::columnTypeRequiresCasting(), CPU, DEBUG_TIMER, CompilationOptions::device_type, entry_point_func_, executor_, generate_column_heads_load(), generateCastsForInputTypes(), generateTableFunctionCall(), get_bit_width(), get_fp_ptr_type(), get_int_ptr_type(), get_int_type(), GPU, table_functions::TableFunction::hasOutputSizeKnownPreLaunch(), table_functions::TableFunction::hasPreFlightOutputSizer(), TableFunctionExecutionUnit::input_exprs, table_functions::TableFunction::mayRequireCastingInputTypes(), passColumnsByValue(), TableFunctionExecutionUnit::table_func, TableFunctionExecutionUnit::target_exprs, to_string(), table_functions::TableFunction::usesManager(), and verify_function_ir().

Referenced by compile().

526  {
527  auto timer = DEBUG_TIMER(__func__);
529  CHECK_EQ(entry_point_func_->arg_size(), 7);
530  auto arg_it = entry_point_func_->arg_begin();
531  const auto mgr_ptr = &*arg_it;
532  const auto input_cols_arg = &*(++arg_it);
533  const auto input_row_counts_arg = &*(++arg_it);
534  const auto input_str_dict_proxies_arg = &*(++arg_it);
535  const auto output_buffers_arg = &*(++arg_it);
536  const auto output_str_dict_proxies_arg = &*(++arg_it);
537  const auto output_row_count_ptr = &*(++arg_it);
538  auto cgen_state = executor_->getCgenStatePtr();
539  CHECK(cgen_state);
540  auto& ctx = cgen_state->context_;
541 
542  llvm::BasicBlock* bb_entry =
543  llvm::BasicBlock::Create(ctx, ".entry", entry_point_func_, 0);
544  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
545 
546  llvm::BasicBlock* bb_exit = llvm::BasicBlock::Create(ctx, ".exit", entry_point_func_);
547 
548  llvm::BasicBlock* func_body_bb = llvm::BasicBlock::Create(
549  ctx, ".func_body0", cgen_state->ir_builder_.GetInsertBlock()->getParent());
550 
551  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
552  cgen_state->ir_builder_.CreateBr(func_body_bb);
553 
554  cgen_state->ir_builder_.SetInsertPoint(func_body_bb);
555  auto col_heads = generate_column_heads_load(
556  exe_unit.input_exprs.size(), input_cols_arg, cgen_state->ir_builder_, ctx);
557  CHECK_EQ(exe_unit.input_exprs.size(), col_heads.size());
558  auto row_count_heads = generate_column_heads_load(
559  exe_unit.input_exprs.size(), input_row_counts_arg, cgen_state->ir_builder_, ctx);
560 
561  auto input_str_dict_proxy_heads = std::vector<llvm::Value*>();
562  if (!emit_only_preflight_fn and co_.device_type == ExecutorDeviceType::CPU) {
563  input_str_dict_proxy_heads = generate_column_heads_load(exe_unit.input_exprs.size(),
564  input_str_dict_proxies_arg,
565  cgen_state->ir_builder_,
566  ctx);
567  }
568  // The column arguments of C++ UDTFs processed by clang must be
569  // passed by reference, see rbc issues 200 and 289.
570  auto pass_column_by_value = passColumnsByValue(exe_unit);
571  std::vector<llvm::Value*> func_args;
572  std::vector<std::pair<llvm::Value*, const SQLTypeInfo>> columns_to_cast;
573  size_t func_arg_index = 0;
574  if (exe_unit.table_func.usesManager()) {
575  func_args.push_back(mgr_ptr);
576  func_arg_index++;
577  }
578  int col_index = -1;
579 
580  for (size_t i = 0; i < exe_unit.input_exprs.size(); i++) {
581  const auto& expr = exe_unit.input_exprs[i];
582  const auto& ti = expr->get_type_info();
583  if (col_index == -1) {
584  func_arg_index += 1;
585  }
586  if (ti.is_fp()) {
587  auto r = cgen_state->ir_builder_.CreateBitCast(
588  col_heads[i], get_fp_ptr_type(get_bit_width(ti), ctx));
589  llvm::LoadInst* scalar_fp = cgen_state->ir_builder_.CreateLoad(
590  r->getType()->getPointerElementType(),
591  r,
592  "input_scalar_fp." + std::to_string(func_arg_index));
593  func_args.push_back(scalar_fp);
594  CHECK_EQ(col_index, -1);
595  } else if (ti.is_integer() || ti.is_boolean() || ti.is_timestamp()) {
596  auto r = cgen_state->ir_builder_.CreateBitCast(
597  col_heads[i], get_int_ptr_type(get_bit_width(ti), ctx));
598  llvm::LoadInst* scalar_int = cgen_state->ir_builder_.CreateLoad(
599  r->getType()->getPointerElementType(),
600  r,
601  "input_scalar_int." + std::to_string(func_arg_index));
602  func_args.push_back(scalar_int);
603  CHECK_EQ(col_index, -1);
604  } else if (ti.is_bytes()) {
605  auto varchar_size =
606  cgen_state->ir_builder_.CreateBitCast(col_heads[i], get_int_ptr_type(64, ctx));
607  auto varchar_ptr = cgen_state->ir_builder_.CreateGEP(
608  col_heads[i]->getType()->getScalarType()->getPointerElementType(),
609  col_heads[i],
610  cgen_state->llInt(8));
611  auto [varchar_struct, varchar_struct_ptr] = alloc_column(
612  std::string("input_varchar_literal.") + std::to_string(func_arg_index),
613  i,
614  ti,
615  varchar_ptr,
616  varchar_size,
617  nullptr,
618  ctx,
619  cgen_state->ir_builder_);
620  func_args.push_back(
621  (pass_column_by_value
622  ? cgen_state->ir_builder_.CreateLoad(
623  varchar_struct->getType()->getPointerElementType(), varchar_struct)
624  : varchar_struct_ptr));
625  CHECK_EQ(col_index, -1);
626  } else if (ti.is_column()) {
627  auto [col, col_ptr] = alloc_column(
628  std::string("input_col.") + std::to_string(func_arg_index),
629  i,
630  ti.get_elem_type(),
631  col_heads[i],
632  row_count_heads[i],
633  (co_.device_type != ExecutorDeviceType::CPU || emit_only_preflight_fn)
634  ? nullptr
635  : input_str_dict_proxy_heads[i],
636  ctx,
637  cgen_state->ir_builder_);
638  func_args.push_back((pass_column_by_value
639  ? cgen_state->ir_builder_.CreateLoad(
640  col->getType()->getPointerElementType(), col)
641  : col_ptr));
642 
643  if (columnTypeRequiresCasting(ti) &&
645  columns_to_cast.push_back(std::make_pair(col_ptr, ti));
646  }
647  CHECK_EQ(col_index, -1);
648  } else if (ti.is_column_list()) {
649  if (col_index == -1) {
650  auto col_list = alloc_column_list(
651  std::string("input_col_list.") + std::to_string(func_arg_index),
652  ti.get_elem_type(),
653  col_heads[i],
654  ti.get_dimension(),
655  row_count_heads[i],
656  (emit_only_preflight_fn) ? nullptr : input_str_dict_proxy_heads[i],
657  ctx,
658  cgen_state->ir_builder_);
659  func_args.push_back(col_list);
660  }
661  col_index++;
662  if (col_index + 1 == ti.get_dimension()) {
663  col_index = -1;
664  }
665  } else {
666  throw std::runtime_error(
667  "Only integer and floating point columns or scalars are supported as inputs to "
668  "table "
669  "functions, got " +
670  ti.get_type_name());
671  }
672  }
673  auto output_str_dict_proxy_heads =
675  ? (generate_column_heads_load(exe_unit.target_exprs.size(),
676  output_str_dict_proxies_arg,
677  cgen_state->ir_builder_,
678  ctx))
679  : std::vector<llvm::Value*>();
680 
681  std::vector<llvm::Value*> output_col_args;
682  for (size_t i = 0; i < exe_unit.target_exprs.size(); i++) {
683  auto* gep = cgen_state->ir_builder_.CreateGEP(
684  output_buffers_arg->getType()->getScalarType()->getPointerElementType(),
685  output_buffers_arg,
686  cgen_state->llInt(i));
687  auto output_load =
688  cgen_state->ir_builder_.CreateLoad(gep->getType()->getPointerElementType(), gep);
689  const auto& expr = exe_unit.target_exprs[i];
690  const auto& ti = expr->get_type_info();
691  CHECK(!ti.is_column()); // UDTF output column type is its data type
692  CHECK(!ti.is_column_list()); // TODO: when UDTF outputs column_list, convert it to
693  // output columns
694  auto [col, col_ptr] = alloc_column(
695  std::string("output_col.") + std::to_string(i),
696  i,
697  ti,
699  ? output_load
700  : nullptr), // CPU: set_output_row_size will set the output
701  // Column ptr member
702  output_row_count_ptr,
703  co_.device_type == ExecutorDeviceType::CPU ? output_str_dict_proxy_heads[i]
704  : nullptr,
705  ctx,
706  cgen_state->ir_builder_);
707  if (co_.device_type == ExecutorDeviceType::CPU && !emit_only_preflight_fn) {
708  cgen_state->emitExternalCall(
709  "TableFunctionManager_register_output_column",
710  llvm::Type::getVoidTy(ctx),
711  {mgr_ptr, llvm::ConstantInt::get(get_int_type(32, ctx), i, true), col_ptr});
712  }
713  output_col_args.push_back((pass_column_by_value ? col : col_ptr));
714  }
715 
716  // output column members must be set before loading column when
717  // column instances are passed by value
718  if ((exe_unit.table_func.hasOutputSizeKnownPreLaunch() ||
719  exe_unit.table_func.hasPreFlightOutputSizer()) &&
720  (co_.device_type == ExecutorDeviceType::CPU) && !emit_only_preflight_fn) {
721  cgen_state->emitExternalCall(
722  "TableFunctionManager_set_output_row_size",
723  llvm::Type::getVoidTy(ctx),
724  {mgr_ptr,
725  cgen_state->ir_builder_.CreateLoad(
726  output_row_count_ptr->getType()->getPointerElementType(),
727  output_row_count_ptr)});
728  }
729 
730  if (!emit_only_preflight_fn) {
731  for (auto& col : output_col_args) {
732  func_args.push_back((pass_column_by_value
733  ? cgen_state->ir_builder_.CreateLoad(
734  col->getType()->getPointerElementType(), col)
735  : col));
736  }
737  }
738 
739  if (exe_unit.table_func.mayRequireCastingInputTypes() && !emit_only_preflight_fn) {
740  generateCastsForInputTypes(exe_unit, columns_to_cast, mgr_ptr);
741  }
742 
744  exe_unit, func_args, bb_exit, output_row_count_ptr, emit_only_preflight_fn);
745 
746  // std::cout << "=================================" << std::endl;
747  // entry_point_func_->print(llvm::outs());
748  // std::cout << "=================================" << std::endl;
749 
751 }
llvm::Type * get_fp_ptr_type(const int width, llvm::LLVMContext &context)
#define CHECK_EQ(x, y)
Definition: Logger.h:230
bool passColumnsByValue(const TableFunctionExecutionUnit &exe_unit)
std::vector< Analyzer::Expr * > input_exprs
const table_functions::TableFunction table_func
std::tuple< llvm::Value *, llvm::Value * > alloc_column(std::string col_name, const size_t index, const SQLTypeInfo &data_target_info, llvm::Value *data_ptr, llvm::Value *data_size, llvm::Value *data_str_dict_proxy_ptr, llvm::LLVMContext &ctx, llvm::IRBuilder<> &ir_builder)
void generateCastsForInputTypes(const TableFunctionExecutionUnit &exe_unit, const std::vector< std::pair< llvm::Value *, const SQLTypeInfo >> &columns_to_cast, llvm::Value *mgr_ptr)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::Value * alloc_column_list(std::string col_list_name, const SQLTypeInfo &data_target_info, llvm::Value *data_ptrs, int length, llvm::Value *data_size, llvm::Value *data_str_dict_proxy_ptrs, llvm::LLVMContext &ctx, llvm::IRBuilder<> &ir_builder)
std::string to_string(char const *&&v)
void verify_function_ir(const llvm::Function *func)
size_t get_bit_width(const SQLTypeInfo &ti)
void generateTableFunctionCall(const TableFunctionExecutionUnit &exe_unit, const std::vector< llvm::Value * > &func_args, llvm::BasicBlock *bb_exit, llvm::Value *output_row_count_ptr, bool emit_only_preflight_fn)
ExecutorDeviceType device_type
std::vector< llvm::Value * > generate_column_heads_load(const int num_columns, llvm::Value *byte_stream_arg, llvm::IRBuilder<> &ir_builder, llvm::LLVMContext &ctx)
#define CHECK(condition)
Definition: Logger.h:222
#define DEBUG_TIMER(name)
Definition: Logger.h:371
std::vector< Analyzer::Expr * > target_exprs
llvm::Type * get_int_ptr_type(const int width, llvm::LLVMContext &context)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateGpuKernel ( )
private

Definition at line 834 of file TableFunctionCompilationContext.cpp.

References CHECK, CHECK_EQ, DEBUG_TIMER, entry_point_func_, executor_, get_int_type(), and kernel_func_.

Referenced by compile().

834  {
835  auto timer = DEBUG_TIMER(__func__);
837  std::vector<llvm::Type*> arg_types;
838  arg_types.reserve(entry_point_func_->arg_size());
839  std::for_each(entry_point_func_->arg_begin(),
840  entry_point_func_->arg_end(),
841  [&arg_types](const auto& arg) { arg_types.push_back(arg.getType()); });
842  CHECK_EQ(arg_types.size(), entry_point_func_->arg_size());
843 
844  auto cgen_state = executor_->getCgenStatePtr();
845  CHECK(cgen_state);
846  auto& ctx = cgen_state->context_;
847 
848  std::vector<llvm::Type*> wrapper_arg_types(arg_types.size() + 1);
849  wrapper_arg_types[0] = llvm::PointerType::get(get_int_type(32, ctx), 0);
850  wrapper_arg_types[1] = arg_types[0];
851 
852  for (size_t i = 1; i < arg_types.size(); ++i) {
853  wrapper_arg_types[i + 1] = arg_types[i];
854  }
855 
856  auto wrapper_ft =
857  llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), wrapper_arg_types, false);
858  kernel_func_ = llvm::Function::Create(wrapper_ft,
859  llvm::Function::ExternalLinkage,
860  "table_func_kernel",
861  cgen_state->module_);
862 
863  auto wrapper_bb_entry = llvm::BasicBlock::Create(ctx, ".entry", kernel_func_, 0);
864  llvm::IRBuilder<> b(ctx);
865  b.SetInsertPoint(wrapper_bb_entry);
866  std::vector<llvm::Value*> loaded_args = {kernel_func_->arg_begin() + 1};
867  for (size_t i = 2; i < wrapper_arg_types.size(); ++i) {
868  loaded_args.push_back(kernel_func_->arg_begin() + i);
869  }
870  auto error_lv = b.CreateCall(entry_point_func_, loaded_args);
871  b.CreateStore(error_lv, kernel_func_->arg_begin());
872  b.CreateRetVoid();
873 }
#define CHECK_EQ(x, y)
Definition: Logger.h:230
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
#define CHECK(condition)
Definition: Logger.h:222
#define DEBUG_TIMER(name)
Definition: Logger.h:371

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateTableFunctionCall ( const TableFunctionExecutionUnit exe_unit,
const std::vector< llvm::Value * > &  func_args,
llvm::BasicBlock *  bb_exit,
llvm::Value *  output_row_count_ptr,
bool  emit_only_preflight_fn 
)
private

Definition at line 483 of file TableFunctionCompilationContext.cpp.

References entry_point_func_, executor_, get_int_type(), table_functions::TableFunction::getName(), table_functions::TableFunction::getPreFlightFnName(), and TableFunctionExecutionUnit::table_func.

Referenced by generateEntryPoint().

488  {
489  auto cgen_state = executor_->getCgenStatePtr();
490  // Emit llvm IR code to call the table function
491  llvm::LLVMContext& ctx = cgen_state->context_;
492  llvm::IRBuilder<>* ir_builder = &cgen_state->ir_builder_;
493 
494  std::string func_name =
495  (emit_only_preflight_fn ? exe_unit.table_func.getPreFlightFnName()
496  : exe_unit.table_func.getName(false, true));
497  llvm::Value* table_func_return =
498  cgen_state->emitExternalCall(func_name, get_int_type(32, ctx), func_args);
499 
500  table_func_return->setName(emit_only_preflight_fn ? "preflight_check_func_ret"
501  : "table_func_ret");
502 
503  // If table_func_return is non-negative then store the value in
504  // output_row_count and return zero. Otherwise, return
505  // table_func_return that negative value contains the error code.
506  llvm::BasicBlock* bb_exit_0 =
507  llvm::BasicBlock::Create(ctx, ".exit0", entry_point_func_);
508 
509  llvm::Constant* const_zero =
510  llvm::ConstantInt::get(table_func_return->getType(), 0, true);
511  llvm::Value* is_ok = ir_builder->CreateICmpSGE(table_func_return, const_zero);
512  ir_builder->CreateCondBr(is_ok, bb_exit_0, bb_exit);
513 
514  ir_builder->SetInsertPoint(bb_exit_0);
515  llvm::Value* r =
516  ir_builder->CreateIntCast(table_func_return, get_int_type(64, ctx), true);
517  ir_builder->CreateStore(r, output_row_count_ptr);
518  ir_builder->CreateRet(const_zero);
519 
520  ir_builder->SetInsertPoint(bb_exit);
521  ir_builder->CreateRet(table_func_return);
522 }
const table_functions::TableFunction table_func
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string getName(const bool drop_suffix=false, const bool lower=false) const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

TableFunctionCompilationContext& TableFunctionCompilationContext::operator= ( const TableFunctionCompilationContext )
delete
bool TableFunctionCompilationContext::passColumnsByValue ( const TableFunctionExecutionUnit exe_unit)
private

Definition at line 468 of file TableFunctionCompilationContext.cpp.

References co_, CompilationOptions::device_type, executor_, GPU, table_functions::TableFunction::isRuntime(), and TableFunctionExecutionUnit::table_func.

Referenced by generateEntryPoint().

469  {
470  bool is_gpu = co_.device_type == ExecutorDeviceType::GPU;
471  auto mod = executor_->get_rt_udf_module(is_gpu).get();
472  if (mod != nullptr) {
473  auto* flag = mod->getModuleFlag("pass_column_arguments_by_value");
474  if (auto* cnt = llvm::mdconst::extract_or_null<llvm::ConstantInt>(flag)) {
475  return cnt->getZExtValue();
476  }
477  }
478 
479  // fallback to original behavior
480  return exe_unit.table_func.isRuntime();
481 }
const table_functions::TableFunction table_func
ExecutorDeviceType device_type

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Member Data Documentation

const CompilationOptions& TableFunctionCompilationContext::co_
private
llvm::Function* TableFunctionCompilationContext::entry_point_func_
private
llvm::Function* TableFunctionCompilationContext::kernel_func_
private

Definition at line 60 of file TableFunctionCompilationContext.h.

Referenced by finalize(), and generateGpuKernel().


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