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

#include <TableFunctionCompilationContext.h>

+ Collaboration diagram for TableFunctionCompilationContext:

Public Types

using FuncPtr = int32_t(*)(const int8_t **input_cols, const int64_t *input_row_count, int64_t **out, int64_t *output_row_count)
 

Public Member Functions

 TableFunctionCompilationContext ()
 
 TableFunctionCompilationContext (const TableFunctionCompilationContext &)=delete
 
TableFunctionCompilationContextoperator= (const TableFunctionCompilationContext &)=delete
 
void compile (const TableFunctionExecutionUnit &exe_unit, const CompilationOptions &co, Executor *executor)
 
TableFunctionCompilationContext::FuncPtr getFuncPtr () const
 
GpuCompilationContextgetGpuCode () const
 

Private Member Functions

void generateEntryPoint (const TableFunctionExecutionUnit &exe_unit)
 
void generateGpuKernel ()
 
void finalize (const CompilationOptions &co, Executor *executor)
 

Private Attributes

std::unique_ptr< CgenStatecgen_state_
 
std::unique_ptr< llvm::Module > module_
 
ExecutionEngineWrapper own_execution_engine_
 
std::shared_ptr
< GpuCompilationContext
gpu_code_
 
llvm::Function * entry_point_func_
 
llvm::Function * kernel_func_
 
FuncPtr func_ptr
 

Detailed Description

Definition at line 29 of file TableFunctionCompilationContext.h.

Member Typedef Documentation

using TableFunctionCompilationContext::FuncPtr = int32_t (*)(const int8_t** input_cols, const int64_t* input_row_count, int64_t** out, int64_t* output_row_count)

Definition at line 45 of file TableFunctionCompilationContext.h.

Constructor & Destructor Documentation

TableFunctionCompilationContext::TableFunctionCompilationContext ( )

Definition at line 142 of file TableFunctionCompilationContext.cpp.

143  : cgen_state_(std::make_unique<CgenState>(std::vector<InputTableInfo>{}, false)) {
TableFunctionCompilationContext::TableFunctionCompilationContext ( const TableFunctionCompilationContext )
delete

Member Function Documentation

void TableFunctionCompilationContext::compile ( const TableFunctionExecutionUnit exe_unit,
const CompilationOptions co,
Executor executor 
)

Definition at line 154 of file TableFunctionCompilationContext.cpp.

References CompilationOptions::device_type, finalize(), generateEntryPoint(), generateGpuKernel(), and GPU.

Referenced by Executor::executeTableFunction().

156  {
157  generateEntryPoint(exe_unit);
160  }
161  finalize(co, executor);
162 }
void generateEntryPoint(const TableFunctionExecutionUnit &exe_unit)
ExecutorDeviceType device_type
void finalize(const CompilationOptions &co, Executor *executor)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::finalize ( const CompilationOptions co,
Executor executor 
)
private

Definition at line 324 of file TableFunctionCompilationContext.cpp.

References cgen_state_, CHECK(), CompilationOptions::device_type, entry_point_func_, func_ptr, CodeGenerator::generateNativeCPUCode(), CodeGenerator::generateNativeGPUCode(), GPU, gpu_code_, logger::IR, kernel_func_, CodeGenerator::link_udf_module(), LOG, module_, own_execution_engine_, rt_udf_cpu_module, and serialize_llvm_object().

Referenced by compile().

325  {
326  if (rt_udf_cpu_module != nullptr) {
327  /*
328  TODO 1: eliminate need for OverrideFromSrc
329  TODO 2: detect and link only the udf's that are needed
330  */
332  *module_,
333  cgen_state_.get(),
334  llvm::Linker::Flags::OverrideFromSrc);
335  }
336 
337  module_.release();
338  // Add code to cache?
339 
340  LOG(IR) << "Table Function Entry Point IR\n"
342 
344  LOG(IR) << "Table Function Kernel IR\n" << serialize_llvm_object(kernel_func_);
345 
346  CHECK(executor);
347  executor->initializeNVPTXBackend();
348  const auto cuda_mgr = executor->catalog_->getDataMgr().getCudaMgr();
349  CHECK(cuda_mgr);
350 
351  CodeGenerator::GPUTarget gpu_target{executor->nvptx_target_machine_.get(),
352  cuda_mgr,
353  executor->blockSize(),
354  cgen_state_.get(),
355  false};
357  kernel_func_,
359  co,
360  gpu_target);
361  } else {
362  auto ee =
364  func_ptr = reinterpret_cast<FuncPtr>(ee->getPointerToFunction(entry_point_func_));
365  own_execution_engine_ = std::move(ee);
366  }
367 
368  LOG(IR) << "End of IR";
369 }
std::unique_ptr< llvm::Module > rt_udf_cpu_module
#define LOG(tag)
Definition: Logger.h:188
std::shared_ptr< GpuCompilationContext > gpu_code_
int32_t(*)(const int8_t **input_cols, const int64_t *input_row_count, int64_t **out, int64_t *output_row_count) FuncPtr
std::unique_ptr< llvm::Module > module_
static ExecutionEngineWrapper generateNativeCPUCode(llvm::Function *func, const std::unordered_set< llvm::Function * > &live_funcs, const CompilationOptions &co)
static std::shared_ptr< GpuCompilationContext > generateNativeGPUCode(llvm::Function *func, llvm::Function *wrapper_func, const std::unordered_set< llvm::Function * > &live_funcs, const CompilationOptions &co, const GPUTarget &gpu_target)
CHECK(cgen_state)
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)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateEntryPoint ( const TableFunctionExecutionUnit exe_unit)
private

Definition at line 164 of file TableFunctionCompilationContext.cpp.

References anonymous_namespace{TableFunctionCompilationContext.cpp}::alloc_column(), cgen_state, cgen_state_, CHECK(), CHECK_EQ, entry_point_func_, generate_column_heads_load(), get_bit_width(), get_fp_type(), get_int_type(), TableFunctionExecutionUnit::input_exprs, TableFunctionExecutionUnit::table_func_name, TableFunctionExecutionUnit::target_exprs, to_lower(), to_string(), and verify_function_ir().

Referenced by compile().

165  {
167  auto arg_it = entry_point_func_->arg_begin();
168  const auto input_cols_arg = &*arg_it;
169  const auto input_row_count = &*(++arg_it);
170  const auto output_buffers_arg = &*(++arg_it);
171  const auto output_row_count_ptr = &*(++arg_it);
172 
173  auto cgen_state = cgen_state_.get();
174  CHECK(cgen_state);
175  auto& ctx = cgen_state->context_;
176 
177  const auto bb_entry = llvm::BasicBlock::Create(ctx, ".entry", entry_point_func_, 0);
178  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
179 
180  const auto bb_exit = llvm::BasicBlock::Create(ctx, ".exit", entry_point_func_);
181 
182  const auto func_body_bb = llvm::BasicBlock::Create(
183  ctx, ".func_body", cgen_state->ir_builder_.GetInsertBlock()->getParent());
184  cgen_state->ir_builder_.SetInsertPoint(func_body_bb);
185 
186  auto col_heads = generate_column_heads_load(
187  exe_unit.input_exprs.size(), input_cols_arg, cgen_state->ir_builder_, ctx);
188  CHECK_EQ(exe_unit.input_exprs.size(), col_heads.size());
189 
190  std::vector<llvm::Value*> func_args;
191  for (size_t i = 0; i < exe_unit.input_exprs.size(); i++) {
192  const auto& expr = exe_unit.input_exprs[i];
193  const auto& ti = expr->get_type_info();
194  if (ti.is_fp()) {
195  auto r = cgen_state->ir_builder_.CreateBitCast(
196  col_heads[i], llvm::PointerType::get(get_fp_type(get_bit_width(ti), ctx), 0));
197  func_args.push_back(cgen_state->ir_builder_.CreateLoad(r));
198  } else if (ti.is_integer()) {
199  auto r = cgen_state->ir_builder_.CreateBitCast(
200  col_heads[i], llvm::PointerType::get(get_int_type(get_bit_width(ti), ctx), 0));
201  func_args.push_back(cgen_state->ir_builder_.CreateLoad(r));
202  } else if (ti.is_column()) {
203  auto col = alloc_column(std::string("input_col.") + std::to_string(i),
204  ti,
205  col_heads[i],
206  input_row_count,
207  ctx,
208  cgen_state_->ir_builder_);
209  func_args.push_back(cgen_state->ir_builder_.CreateLoad(col));
210  } else {
211  throw std::runtime_error(
212  "Only integer and floating point columns or scalars are supported as inputs to "
213  "table "
214  "functions.");
215  }
216  }
217 
218  std::vector<llvm::Value*> output_col_args;
219  for (size_t i = 0; i < exe_unit.target_exprs.size(); i++) {
220  auto output_load = cgen_state->ir_builder_.CreateLoad(
221  cgen_state->ir_builder_.CreateGEP(output_buffers_arg, cgen_state_->llInt(i)));
222  const auto& expr = exe_unit.target_exprs[i];
223  const auto& ti = expr->get_type_info();
224  /*
225  How to specify output scalars in C++ code?
226  */
227  if (ti.is_fp()) {
228  func_args.push_back(cgen_state->ir_builder_.CreateBitCast(
229  output_load, llvm::PointerType::get(get_fp_type(get_bit_width(ti), ctx), 0)));
230  } else if (ti.is_integer()) {
231  func_args.push_back(cgen_state->ir_builder_.CreateBitCast(
232  output_load, llvm::PointerType::get(get_int_type(get_bit_width(ti), ctx), 0)));
233  } else if (ti.is_column()) {
234  auto col = alloc_column(std::string("output_col.") + std::to_string(i),
235  ti,
236  output_load,
237  output_row_count_ptr,
238  ctx,
239  cgen_state_->ir_builder_);
240  func_args.push_back(cgen_state->ir_builder_.CreateLoad(col));
241  } else {
242  throw std::runtime_error(
243  "Only integer and floating point columns are supported as outputs to table "
244  "functions.");
245  }
246  }
247 
248  auto func_name = exe_unit.table_func_name;
249  boost::algorithm::to_lower(func_name);
250  const auto table_func_return =
251  cgen_state->emitExternalCall(func_name, get_int_type(32, ctx), func_args);
252  table_func_return->setName("table_func_ret");
253 
254  // If table_func_return is non-negative then store the value in
255  // output_row_count and return zero. Otherwise, return
256  // table_func_return that negative value contains the error code.
257  const auto bb_exit_0 = llvm::BasicBlock::Create(ctx, ".exit0", entry_point_func_);
258 
259  auto const_zero = llvm::ConstantInt::get(table_func_return->getType(), 0, true);
260  auto is_ok = cgen_state_->ir_builder_.CreateICmpSGE(table_func_return, const_zero);
261  cgen_state_->ir_builder_.CreateCondBr(is_ok, bb_exit_0, bb_exit);
262 
263  cgen_state_->ir_builder_.SetInsertPoint(bb_exit_0);
264  auto r = cgen_state->ir_builder_.CreateIntCast(
265  table_func_return, get_int_type(64, ctx), true);
266  cgen_state->ir_builder_.CreateStore(r, output_row_count_ptr);
267  cgen_state->ir_builder_.CreateRet(const_zero);
268 
269  cgen_state->ir_builder_.SetInsertPoint(bb_exit);
270  cgen_state->ir_builder_.CreateRet(table_func_return);
271 
272  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
273  cgen_state->ir_builder_.CreateBr(func_body_bb);
274 
275  /*
276  std::cout << "=================================" << std::endl;
277  entry_point_func_->print(llvm::outs());
278  std::cout << "=================================" << std::endl;
279  */
280 
282 }
std::string to_lower(const std::string &str)
#define CHECK_EQ(x, y)
Definition: Logger.h:205
const std::string table_func_name
std::vector< Analyzer::Expr * > input_exprs
llvm::Type * get_fp_type(const int width, llvm::LLVMContext &context)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string to_string(char const *&&v)
false auto cgen_state
void verify_function_ir(const llvm::Function *func)
size_t get_bit_width(const SQLTypeInfo &ti)
CHECK(cgen_state)
std::vector< llvm::Value * > generate_column_heads_load(const int num_columns, llvm::Value *byte_stream_arg, llvm::IRBuilder<> &ir_builder, llvm::LLVMContext &ctx)
std::vector< Analyzer::Expr * > target_exprs
llvm::Value * alloc_column(std::string col_name, const SQLTypeInfo &data_target_info, llvm::Value *data_ptr, llvm::Value *data_size, llvm::LLVMContext &ctx, llvm::IRBuilder<> &ir_builder)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateGpuKernel ( )
private

Definition at line 284 of file TableFunctionCompilationContext.cpp.

References cgen_state, cgen_state_, CHECK(), CHECK_EQ, entry_point_func_, get_int_type(), and kernel_func_.

Referenced by compile().

284  {
286  std::vector<llvm::Type*> arg_types;
287  arg_types.reserve(entry_point_func_->arg_size());
288  std::for_each(entry_point_func_->arg_begin(),
289  entry_point_func_->arg_end(),
290  [&arg_types](const auto& arg) { arg_types.push_back(arg.getType()); });
291  CHECK_EQ(arg_types.size(), entry_point_func_->arg_size());
292 
293  auto cgen_state = cgen_state_.get();
294  CHECK(cgen_state);
295  auto& ctx = cgen_state->context_;
296 
297  std::vector<llvm::Type*> wrapper_arg_types(arg_types.size() + 1);
298  wrapper_arg_types[0] = llvm::PointerType::get(get_int_type(32, ctx), 0);
299  wrapper_arg_types[1] = arg_types[0];
300 
301  for (size_t i = 1; i < arg_types.size(); ++i) {
302  wrapper_arg_types[i + 1] = arg_types[i];
303  }
304 
305  auto wrapper_ft =
306  llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), wrapper_arg_types, false);
307  kernel_func_ = llvm::Function::Create(wrapper_ft,
308  llvm::Function::ExternalLinkage,
309  "table_func_kernel",
310  cgen_state->module_);
311 
312  auto wrapper_bb_entry = llvm::BasicBlock::Create(ctx, ".entry", kernel_func_, 0);
313  llvm::IRBuilder<> b(ctx);
314  b.SetInsertPoint(wrapper_bb_entry);
315  std::vector<llvm::Value*> loaded_args = {kernel_func_->arg_begin() + 1};
316  for (size_t i = 2; i < wrapper_arg_types.size(); ++i) {
317  loaded_args.push_back(kernel_func_->arg_begin() + i);
318  }
319  auto error_lv = b.CreateCall(entry_point_func_, loaded_args);
320  b.CreateStore(error_lv, kernel_func_->arg_begin());
321  b.CreateRetVoid();
322 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
false auto cgen_state
CHECK(cgen_state)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

TableFunctionCompilationContext::FuncPtr TableFunctionCompilationContext::getFuncPtr ( ) const
inline

Definition at line 46 of file TableFunctionCompilationContext.h.

References func_ptr.

Referenced by TableFunctionExecutionContext::launchCpuCode().

+ Here is the caller graph for this function:

GpuCompilationContext* TableFunctionCompilationContext::getGpuCode ( ) const
inline

Definition at line 48 of file TableFunctionCompilationContext.h.

References gpu_code_.

Referenced by TableFunctionExecutionContext::launchGpuCode().

48 { return gpu_code_.get(); }
std::shared_ptr< GpuCompilationContext > gpu_code_

+ Here is the caller graph for this function:

TableFunctionCompilationContext& TableFunctionCompilationContext::operator= ( const TableFunctionCompilationContext )
delete

Member Data Documentation

std::unique_ptr<CgenState> TableFunctionCompilationContext::cgen_state_
private
llvm::Function* TableFunctionCompilationContext::entry_point_func_
private
FuncPtr TableFunctionCompilationContext::func_ptr
private

Definition at line 61 of file TableFunctionCompilationContext.h.

Referenced by finalize(), and getFuncPtr().

std::shared_ptr<GpuCompilationContext> TableFunctionCompilationContext::gpu_code_
private

Definition at line 58 of file TableFunctionCompilationContext.h.

Referenced by finalize(), and getGpuCode().

llvm::Function* TableFunctionCompilationContext::kernel_func_
private

Definition at line 60 of file TableFunctionCompilationContext.h.

Referenced by finalize(), and generateGpuKernel().

std::unique_ptr<llvm::Module> TableFunctionCompilationContext::module_
private

Definition at line 56 of file TableFunctionCompilationContext.h.

Referenced by finalize().

ExecutionEngineWrapper TableFunctionCompilationContext::own_execution_engine_
private

Definition at line 57 of file TableFunctionCompilationContext.h.

Referenced by finalize().


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