OmniSciDB  c1a53651b2
 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:291
#define DEBUG_TIMER(name)
Definition: Logger.h:411
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 861 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().

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

+ 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 739 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().

742  {
743  auto* cgen_state = executor_->getCgenStatePtr();
744  llvm::LLVMContext& ctx = cgen_state->context_;
745  llvm::IRBuilder<>* ir_builder = &cgen_state->ir_builder_;
746  CodeGenerator codeGenerator = CodeGenerator(cgen_state, executor_->getPlanStatePtr());
747  llvm::Function* old_func = cgen_state->current_func_;
748  cgen_state->current_func_ =
749  entry_point_func_; // update cgen_state current func for CodeGenerator
750 
751  for (unsigned i = 0; i < columns_to_cast.size(); ++i) {
752  auto [col_ptr, ti] = columns_to_cast[i];
753 
754  if (ti.is_column() && ti.get_subtype() == kTIMESTAMP && ti.get_precision() != 9) {
755  // TIMESTAMP columns should always have nanosecond precision
756  SQLTypeInfo orig_ti = SQLTypeInfo(
757  ti.get_subtype(), ti.get_precision(), ti.get_dimension(), ti.get_notnull());
758  SQLTypeInfo dest_ti =
759  SQLTypeInfo(kTIMESTAMP, 9, ti.get_dimension(), ti.get_notnull());
760  cast_column(col_ptr,
762  orig_ti,
763  dest_ti,
764  std::to_string(i + 1),
765  *ir_builder,
766  ctx,
767  codeGenerator);
768  }
769  }
770 
771  // The QueryEngine CodeGenerator will codegen return values corresponding to
772  // QueryExecutionError codes. Since at the table function level we'd like error handling
773  // to be done by the TableFunctionManager, we replace the codegen'd returns by calls to
774  // the appropriate Manager functions.
776  // TableFunctionManager is not supported on GPU, so leave the QueryExecutionError code
777  return;
778  }
779 
780  std::vector<llvm::ReturnInst*> rets_to_replace;
781  for (llvm::BasicBlock& BB : *entry_point_func_) {
782  for (llvm::Instruction& I : BB) {
783  if (!llvm::isa<llvm::ReturnInst>(&I)) {
784  continue;
785  }
786  llvm::ReturnInst* RI = llvm::cast<llvm::ReturnInst>(&I);
787  llvm::Value* retValue = RI->getReturnValue();
788  if (!retValue || !llvm::isa<llvm::ConstantInt>(retValue)) {
789  continue;
790  }
791  llvm::ConstantInt* retConst = llvm::cast<llvm::ConstantInt>(retValue);
792  if (retConst->getValue() == 7) {
793  // ret 7 = underflow/overflow during casting attempt
794  rets_to_replace.push_back(RI);
795  }
796  }
797  }
798 
799  auto prev_insert_point = ir_builder->saveIP();
800  for (llvm::ReturnInst* RI : rets_to_replace) {
801  ir_builder->SetInsertPoint(RI);
802  llvm::Value* err_msg = ir_builder->CreateGlobalStringPtr(
803  "Underflow or overflow during casting of input types!", "cast_err_str");
804  llvm::Value* error_call;
805  if (exe_unit.table_func.usesManager()) {
806  error_call = cgen_state->emitExternalCall("TableFunctionManager_error_message",
807  ir_builder->getInt32Ty(),
808  {mgr_ptr, err_msg});
809  } else {
810  error_call = cgen_state->emitExternalCall(
811  "table_function_error", ir_builder->getInt32Ty(), {err_msg});
812  }
813  llvm::ReplaceInstWithInst(RI, llvm::ReturnInst::Create(ctx, error_call));
814  }
815  ir_builder->restoreIP(prev_insert_point);
816 
817  cgen_state->current_func_ = old_func;
818 }
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  ti.is_timeinterval()) {
582  auto r = cgen_state->ir_builder_.CreateBitCast(
583  col_heads[i], get_int_ptr_type(get_bit_width(ti), ctx));
584  llvm::LoadInst* scalar_int = cgen_state->ir_builder_.CreateLoad(
585  r->getType()->getPointerElementType(),
586  r,
587  "input_scalar_int." + std::to_string(func_arg_index));
588  func_args.push_back(scalar_int);
589  CHECK_EQ(col_index, -1);
590  } else if (ti.is_bytes()) {
591  auto varchar_size =
592  cgen_state->ir_builder_.CreateBitCast(col_heads[i], get_int_ptr_type(64, ctx));
593  auto varchar_ptr = cgen_state->ir_builder_.CreateGEP(
594  col_heads[i]->getType()->getScalarType()->getPointerElementType(),
595  col_heads[i],
596  cgen_state->llInt(8));
597  auto [varchar_struct, varchar_struct_ptr] = alloc_column(
598  std::string("input_varchar_literal.") + std::to_string(func_arg_index),
599  i,
600  ti,
601  varchar_ptr,
602  varchar_size,
603  nullptr,
604  ctx,
605  cgen_state->ir_builder_);
606  func_args.push_back(
607  (pass_column_by_value
608  ? cgen_state->ir_builder_.CreateLoad(
609  varchar_struct->getType()->getPointerElementType(), varchar_struct)
610  : varchar_struct_ptr));
611  CHECK_EQ(col_index, -1);
612  } else if (ti.is_column()) {
613  auto [col, col_ptr] = alloc_column(
614  std::string("input_col.") + std::to_string(func_arg_index),
615  i,
616  ti.get_elem_type(),
617  col_heads[i],
618  row_count_heads[i],
619  (co_.device_type != ExecutorDeviceType::CPU || emit_only_preflight_fn)
620  ? nullptr
621  : input_str_dict_proxy_heads[i],
622  ctx,
623  cgen_state->ir_builder_);
624  func_args.push_back((pass_column_by_value
625  ? cgen_state->ir_builder_.CreateLoad(
626  col->getType()->getPointerElementType(), col)
627  : col_ptr));
628 
629  if (columnTypeRequiresCasting(ti) &&
631  columns_to_cast.push_back(std::make_pair(col_ptr, ti));
632  }
633  CHECK_EQ(col_index, -1);
634  } else if (ti.is_column_list()) {
635  if (col_index == -1) {
636  auto col_list = alloc_column_list(
637  std::string("input_col_list.") + std::to_string(func_arg_index),
638  ti.get_elem_type(),
639  col_heads[i],
640  ti.get_dimension(),
641  row_count_heads[i],
642  (emit_only_preflight_fn) ? nullptr : input_str_dict_proxy_heads[i],
643  ctx,
644  cgen_state->ir_builder_);
645  func_args.push_back(col_list);
646  }
647  col_index++;
648  if (col_index + 1 == ti.get_dimension()) {
649  col_index = -1;
650  }
651  } else {
652  throw std::runtime_error(
653  "Only integer and floating point columns or scalars are supported as inputs to "
654  "table "
655  "functions, got " +
656  ti.get_type_name());
657  }
658  }
659  auto output_str_dict_proxy_heads =
661  ? (generate_column_heads_load(exe_unit.target_exprs.size(),
662  output_str_dict_proxies_arg,
663  cgen_state->ir_builder_,
664  ctx))
665  : std::vector<llvm::Value*>();
666 
667  std::vector<llvm::Value*> output_col_args;
668  for (size_t i = 0; i < exe_unit.target_exprs.size(); i++) {
669  auto* gep = cgen_state->ir_builder_.CreateGEP(
670  output_buffers_arg->getType()->getScalarType()->getPointerElementType(),
671  output_buffers_arg,
672  cgen_state->llInt(i));
673  auto output_load =
674  cgen_state->ir_builder_.CreateLoad(gep->getType()->getPointerElementType(), gep);
675  const auto& expr = exe_unit.target_exprs[i];
676  const auto& ti = expr->get_type_info();
677  CHECK(!ti.is_column()); // UDTF output column type is its data type
678  CHECK(!ti.is_column_list()); // TODO: when UDTF outputs column_list, convert it to
679  // output columns
680  auto [col, col_ptr] = alloc_column(
681  std::string("output_col.") + std::to_string(i),
682  i,
683  ti,
685  ? output_load
686  : nullptr), // CPU: set_output_row_size will set the output
687  // Column ptr member
688  output_row_count_ptr,
689  co_.device_type == ExecutorDeviceType::CPU ? output_str_dict_proxy_heads[i]
690  : nullptr,
691  ctx,
692  cgen_state->ir_builder_);
693  if (co_.device_type == ExecutorDeviceType::CPU && !emit_only_preflight_fn) {
694  cgen_state->emitExternalCall(
695  "TableFunctionManager_register_output_column",
696  llvm::Type::getVoidTy(ctx),
697  {mgr_ptr, llvm::ConstantInt::get(get_int_type(32, ctx), i, true), col_ptr});
698  }
699  output_col_args.push_back((pass_column_by_value ? col : col_ptr));
700  }
701 
702  // output column members must be set before loading column when
703  // column instances are passed by value
704  if ((exe_unit.table_func.hasOutputSizeKnownPreLaunch() ||
705  exe_unit.table_func.hasPreFlightOutputSizer()) &&
706  (co_.device_type == ExecutorDeviceType::CPU) && !emit_only_preflight_fn) {
707  cgen_state->emitExternalCall(
708  "TableFunctionManager_set_output_row_size",
709  llvm::Type::getVoidTy(ctx),
710  {mgr_ptr,
711  cgen_state->ir_builder_.CreateLoad(
712  output_row_count_ptr->getType()->getPointerElementType(),
713  output_row_count_ptr)});
714  }
715 
716  if (!emit_only_preflight_fn) {
717  for (auto& col : output_col_args) {
718  func_args.push_back((pass_column_by_value
719  ? cgen_state->ir_builder_.CreateLoad(
720  col->getType()->getPointerElementType(), col)
721  : col));
722  }
723  }
724 
725  if (exe_unit.table_func.mayRequireCastingInputTypes() && !emit_only_preflight_fn) {
726  generateCastsForInputTypes(exe_unit, columns_to_cast, mgr_ptr);
727  }
728 
730  exe_unit, func_args, bb_exit, output_row_count_ptr, emit_only_preflight_fn);
731 
732  // std::cout << "=================================" << std::endl;
733  // entry_point_func_->print(llvm::outs());
734  // std::cout << "=================================" << std::endl;
735 
737 }
llvm::Type * get_fp_ptr_type(const int width, llvm::LLVMContext &context)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
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:291
#define DEBUG_TIMER(name)
Definition: Logger.h:411
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 820 of file TableFunctionCompilationContext.cpp.

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

Referenced by compile().

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

+ 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: