OmniSciDB  ca0c39ec8f
 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 413 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().

415  {
416  auto timer = DEBUG_TIMER(__func__);
417 
418  // Here we assume that Executor::tf_code_accessor is cleared when a
419  // UDTF implementation is changed. TODO: Ideally, the key should
420  // contain a hash of an UDTF implementation string. This could be
421  // achieved by including the hash value to the prefix of the UDTF
422  // name, for instance.
423  CodeCacheKey key{exe_unit.table_func.getName(),
424  exprsKey(exe_unit.input_exprs),
425  exprsKey(exe_unit.target_exprs),
426  std::to_string(emit_only_preflight_fn),
428 
429  auto cached_code = QueryEngine::getInstance()->tf_code_accessor->get_or_wait(key);
430  if (cached_code) {
431  return *cached_code;
432  }
433 
434  auto cgen_state = executor_->getCgenStatePtr();
435  CHECK(cgen_state);
436  CHECK(cgen_state->module_ == nullptr);
437  cgen_state->set_module_shallow_copy(executor_->get_rt_module());
438 
440 
441  generateEntryPoint(exe_unit, emit_only_preflight_fn);
442 
444  CHECK(!emit_only_preflight_fn);
446  }
447 
448  QueryEngine::getInstance()->tf_code_accessor->swap(key,
449  finalize(emit_only_preflight_fn));
450  return QueryEngine::getInstance()->tf_code_accessor->get_value(key);
451 }
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 860 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().

861  {
862  auto timer = DEBUG_TIMER(__func__);
863  /*
864  TODO 1: eliminate need for OverrideFromSrc
865  TODO 2: detect and link only the udf's that are needed
866  */
867  auto cgen_state = executor_->getCgenStatePtr();
868  auto is_gpu = co_.device_type == ExecutorDeviceType::GPU;
869  if (executor_->has_rt_udf_module(is_gpu)) {
870  CodeGenerator::link_udf_module(executor_->get_rt_udf_module(is_gpu),
871  *(cgen_state->module_),
872  cgen_state,
873  llvm::Linker::Flags::OverrideFromSrc);
874  }
875 
876  LOG(IR) << (emit_only_preflight_fn ? "Pre Flight Function Entry Point IR\n"
877  : "Table Function Entry Point IR\n")
879  std::shared_ptr<CompilationContext> code;
880  if (is_gpu) {
881  LOG(IR) << "Table Function Kernel IR\n" << serialize_llvm_object(kernel_func_);
882 
883  CHECK(executor_);
884  executor_->initializeNVPTXBackend();
885 
886  CodeGenerator::GPUTarget gpu_target{executor_->nvptx_target_machine_.get(),
887  executor_->cudaMgr(),
888  executor_->blockSize(),
889  cgen_state,
890  false};
893  kernel_func_,
895  /*is_gpu_smem_used=*/false,
896  co_,
897  gpu_target);
898  } else {
899  auto ee =
901  auto cpu_code = std::make_shared<CpuCompilationContext>(std::move(ee));
902  cpu_code->setFunctionPointer(entry_point_func_);
903  code = cpu_code;
904  }
905  LOG(IR) << "End of IR";
906 
907  return code;
908 }
#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 738 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().

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

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

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

Referenced by compile().

819  {
820  auto timer = DEBUG_TIMER(__func__);
822  std::vector<llvm::Type*> arg_types;
823  arg_types.reserve(entry_point_func_->arg_size());
824  std::for_each(entry_point_func_->arg_begin(),
825  entry_point_func_->arg_end(),
826  [&arg_types](const auto& arg) { arg_types.push_back(arg.getType()); });
827  CHECK_EQ(arg_types.size(), entry_point_func_->arg_size());
828 
829  auto cgen_state = executor_->getCgenStatePtr();
830  CHECK(cgen_state);
831  auto& ctx = cgen_state->context_;
832 
833  std::vector<llvm::Type*> wrapper_arg_types(arg_types.size() + 1);
834  wrapper_arg_types[0] = llvm::PointerType::get(get_int_type(32, ctx), 0);
835  wrapper_arg_types[1] = arg_types[0];
836 
837  for (size_t i = 1; i < arg_types.size(); ++i) {
838  wrapper_arg_types[i + 1] = arg_types[i];
839  }
840 
841  auto wrapper_ft =
842  llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), wrapper_arg_types, false);
843  kernel_func_ = llvm::Function::Create(wrapper_ft,
844  llvm::Function::ExternalLinkage,
845  "table_func_kernel",
846  cgen_state->module_);
847 
848  auto wrapper_bb_entry = llvm::BasicBlock::Create(ctx, ".entry", kernel_func_, 0);
849  llvm::IRBuilder<> b(ctx);
850  b.SetInsertPoint(wrapper_bb_entry);
851  std::vector<llvm::Value*> loaded_args = {kernel_func_->arg_begin() + 1};
852  for (size_t i = 2; i < wrapper_arg_types.size(); ++i) {
853  loaded_args.push_back(kernel_func_->arg_begin() + i);
854  }
855  auto error_lv = b.CreateCall(entry_point_func_, loaded_args);
856  b.CreateStore(error_lv, kernel_func_->arg_begin());
857  b.CreateRetVoid();
858 }
#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 468 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().

473  {
474  auto cgen_state = executor_->getCgenStatePtr();
475  // Emit llvm IR code to call the table function
476  llvm::LLVMContext& ctx = cgen_state->context_;
477  llvm::IRBuilder<>* ir_builder = &cgen_state->ir_builder_;
478 
479  std::string func_name =
480  (emit_only_preflight_fn ? exe_unit.table_func.getPreFlightFnName()
481  : exe_unit.table_func.getName(false, true));
482  llvm::Value* table_func_return =
483  cgen_state->emitExternalCall(func_name, get_int_type(32, ctx), func_args);
484 
485  table_func_return->setName(emit_only_preflight_fn ? "preflight_check_func_ret"
486  : "table_func_ret");
487 
488  // If table_func_return is non-negative then store the value in
489  // output_row_count and return zero. Otherwise, return
490  // table_func_return that negative value contains the error code.
491  llvm::BasicBlock* bb_exit_0 =
492  llvm::BasicBlock::Create(ctx, ".exit0", entry_point_func_);
493 
494  llvm::Constant* const_zero =
495  llvm::ConstantInt::get(table_func_return->getType(), 0, true);
496  llvm::Value* is_ok = ir_builder->CreateICmpSGE(table_func_return, const_zero);
497  ir_builder->CreateCondBr(is_ok, bb_exit_0, bb_exit);
498 
499  ir_builder->SetInsertPoint(bb_exit_0);
500  llvm::Value* r =
501  ir_builder->CreateIntCast(table_func_return, get_int_type(64, ctx), true);
502  ir_builder->CreateStore(r, output_row_count_ptr);
503  ir_builder->CreateRet(const_zero);
504 
505  ir_builder->SetInsertPoint(bb_exit);
506  ir_builder->CreateRet(table_func_return);
507 }
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 453 of file TableFunctionCompilationContext.cpp.

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

Referenced by generateEntryPoint().

454  {
455  bool is_gpu = co_.device_type == ExecutorDeviceType::GPU;
456  auto mod = executor_->get_rt_udf_module(is_gpu).get();
457  if (mod != nullptr) {
458  auto* flag = mod->getModuleFlag("pass_column_arguments_by_value");
459  if (auto* cnt = llvm::mdconst::extract_or_null<llvm::ConstantInt>(flag)) {
460  return cnt->getZExtValue();
461  }
462  }
463 
464  // fallback to original behavior
465  return exe_unit.table_func.isRuntime();
466 }
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: