OmniSciDB  b24e664e58
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
anonymous_namespace{NativeCodegen.cpp} Namespace Reference

Functions

void eliminate_dead_self_recursive_funcs (llvm::Module &M, const std::unordered_set< llvm::Function * > &live_funcs)
 
void optimize_ir (llvm::Function *query_func, llvm::Module *module, const std::unordered_set< llvm::Function * > &live_funcs, const CompilationOptions &co)
 
std::string cpp_to_llvm_name (const std::string &s)
 
std::string gen_array_any_all_sigs ()
 
std::string gen_translate_null_key_sigs ()
 
void bind_pos_placeholders (const std::string &pos_fn_name, const bool use_resume_param, llvm::Function *query_func, llvm::Module *module)
 
void set_row_func_argnames (llvm::Function *row_func, const size_t in_col_count, const size_t agg_col_count, const bool hoist_literals)
 
std::pair< llvm::Function
*, std::vector< llvm::Value * > > 
create_row_function (const size_t in_col_count, const size_t agg_col_count, const bool hoist_literals, llvm::Function *query_func, llvm::Module *module, llvm::LLVMContext &context)
 
void bind_query (llvm::Function *query_func, const std::string &query_fname, llvm::Function *multifrag_query_func, llvm::Module *module)
 
std::vector< std::string > get_agg_fnames (const std::vector< Analyzer::Expr * > &target_exprs, const bool is_group_by)
 
template<typename InstType >
llvm::Value * find_variable_in_basic_block (llvm::Function *func, std::string bb_name, std::string variable_name)
 

Variables

const std::string cuda_rt_decls
 

Function Documentation

void anonymous_namespace{NativeCodegen.cpp}::bind_pos_placeholders ( const std::string &  pos_fn_name,
const bool  use_resume_param,
llvm::Function *  query_func,
llvm::Module *  module 
)

Definition at line 944 of file NativeCodegen.cpp.

References CHECK(), Analyzer::AggExpr::get_aggtype(), kENCODING_NONE, kSAMPLE, and run_benchmark_import::result.

947  {
948  for (auto it = llvm::inst_begin(query_func), e = llvm::inst_end(query_func); it != e;
949  ++it) {
950  if (!llvm::isa<llvm::CallInst>(*it)) {
951  continue;
952  }
953  auto& pos_call = llvm::cast<llvm::CallInst>(*it);
954  if (std::string(pos_call.getCalledFunction()->getName()) == pos_fn_name) {
955  if (use_resume_param) {
956  const auto error_code_arg = get_arg_by_name(query_func, "error_code");
957  llvm::ReplaceInstWithInst(
958  &pos_call,
959  llvm::CallInst::Create(module->getFunction(pos_fn_name + "_impl"),
960  error_code_arg));
961  } else {
962  llvm::ReplaceInstWithInst(
963  &pos_call,
964  llvm::CallInst::Create(module->getFunction(pos_fn_name + "_impl")));
965  }
966  break;
967  }
968  }
969 }
std::unique_ptr< llvm::Module > module(runtime_module_shallow_copy(cgen_state))
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:117

+ Here is the call graph for this function:

void anonymous_namespace{NativeCodegen.cpp}::bind_query ( llvm::Function *  query_func,
const std::string &  query_fname,
llvm::Function *  multifrag_query_func,
llvm::Module *  module 
)

Definition at line 1094 of file NativeCodegen.cpp.

1097  {
1098  std::vector<llvm::CallInst*> query_stubs;
1099  for (auto it = llvm::inst_begin(multifrag_query_func),
1100  e = llvm::inst_end(multifrag_query_func);
1101  it != e;
1102  ++it) {
1103  if (!llvm::isa<llvm::CallInst>(*it)) {
1104  continue;
1105  }
1106  auto& query_call = llvm::cast<llvm::CallInst>(*it);
1107  if (std::string(query_call.getCalledFunction()->getName()) == query_fname) {
1108  query_stubs.push_back(&query_call);
1109  }
1110  }
1111  for (auto& S : query_stubs) {
1112  std::vector<llvm::Value*> args;
1113  for (size_t i = 0; i < S->getNumArgOperands(); ++i) {
1114  args.push_back(S->getArgOperand(i));
1115  }
1116  llvm::ReplaceInstWithInst(S, llvm::CallInst::Create(query_func, args, ""));
1117  }
1118 }
std::string anonymous_namespace{NativeCodegen.cpp}::cpp_to_llvm_name ( const std::string &  s)

Definition at line 335 of file NativeCodegen.cpp.

References CHECK().

Referenced by gen_array_any_all_sigs(), and gen_translate_null_key_sigs().

335  {
336  if (s == "int8_t") {
337  return "i8";
338  }
339  if (s == "int16_t") {
340  return "i16";
341  }
342  if (s == "int32_t") {
343  return "i32";
344  }
345  if (s == "int64_t") {
346  return "i64";
347  }
348  CHECK(s == "float" || s == "double");
349  return s;
350 }
CHECK(cgen_state)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::pair<llvm::Function*, std::vector<llvm::Value*> > anonymous_namespace{NativeCodegen.cpp}::create_row_function ( const size_t  in_col_count,
const size_t  agg_col_count,
const bool  hoist_literals,
llvm::Function *  query_func,
llvm::Module *  module,
llvm::LLVMContext &  context 
)

Definition at line 1020 of file NativeCodegen.cpp.

1026  {
1027  std::vector<llvm::Type*> row_process_arg_types;
1028 
1029  if (agg_col_count) {
1030  // output (aggregate) arguments
1031  for (size_t i = 0; i < agg_col_count; ++i) {
1032  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1033  }
1034  } else {
1035  // group by buffer
1036  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1037  // current match count
1038  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1039  // total match count passed from the caller
1040  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1041  // old total match count returned to the caller
1042  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1043  // max matched (total number of slots in the output buffer)
1044  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1045  }
1046 
1047  // aggregate init values
1048  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1049 
1050  // position argument
1051  row_process_arg_types.push_back(llvm::Type::getInt64Ty(context));
1052 
1053  // fragment row offset argument
1054  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1055 
1056  // number of rows for each scan
1057  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1058 
1059  // literals buffer argument
1060  if (hoist_literals) {
1061  row_process_arg_types.push_back(llvm::Type::getInt8PtrTy(context));
1062  }
1063 
1064  // Generate the function signature and column head fetches s.t.
1065  // double indirection isn't needed in the inner loop
1066  auto& fetch_bb = query_func->front();
1067  llvm::IRBuilder<> fetch_ir_builder(&fetch_bb);
1068  fetch_ir_builder.SetInsertPoint(&*fetch_bb.begin());
1069  auto col_heads = generate_column_heads_load(
1070  in_col_count, query_func->args().begin(), fetch_ir_builder, context);
1071  CHECK_EQ(in_col_count, col_heads.size());
1072 
1073  // column buffer arguments
1074  for (size_t i = 0; i < in_col_count; ++i) {
1075  row_process_arg_types.emplace_back(llvm::Type::getInt8PtrTy(context));
1076  }
1077 
1078  // join hash table argument
1079  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1080 
1081  // generate the function
1082  auto ft =
1083  llvm::FunctionType::get(get_int_type(32, context), row_process_arg_types, false);
1084 
1085  auto row_func =
1086  llvm::Function::Create(ft, llvm::Function::ExternalLinkage, "row_func", module);
1087 
1088  // set the row function argument names; for debugging purposes only
1089  set_row_func_argnames(row_func, in_col_count, agg_col_count, hoist_literals);
1090 
1091  return std::make_pair(row_func, col_heads);
1092 }
#define CHECK_EQ(x, y)
Definition: Logger.h:198
const int64_t const uint32_t const uint32_t const uint32_t agg_col_count
std::unique_ptr< llvm::Module > module(runtime_module_shallow_copy(cgen_state))
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
void set_row_func_argnames(llvm::Function *row_func, const size_t in_col_count, const size_t agg_col_count, const bool hoist_literals)
std::vector< llvm::Value * > generate_column_heads_load(const int num_columns, llvm::Value *byte_stream_arg, llvm::IRBuilder<> &ir_builder, llvm::LLVMContext &ctx)
void anonymous_namespace{NativeCodegen.cpp}::eliminate_dead_self_recursive_funcs ( llvm::Module &  M,
const std::unordered_set< llvm::Function * > &  live_funcs 
)

Definition at line 75 of file NativeCodegen.cpp.

Referenced by optimize_ir().

77  {
78  std::vector<llvm::Function*> dead_funcs;
79  for (auto& F : M) {
80  bool bAlive = false;
81  if (live_funcs.count(&F)) {
82  continue;
83  }
84  for (auto U : F.users()) {
85  auto* C = llvm::dyn_cast<const llvm::CallInst>(U);
86  if (!C || C->getParent()->getParent() != &F) {
87  bAlive = true;
88  break;
89  }
90  }
91  if (!bAlive) {
92  dead_funcs.push_back(&F);
93  }
94  }
95  for (auto pFn : dead_funcs) {
96  pFn->eraseFromParent();
97  }
98 }

+ Here is the caller graph for this function:

template<typename InstType >
llvm::Value* anonymous_namespace{NativeCodegen.cpp}::find_variable_in_basic_block ( llvm::Function *  func,
std::string  bb_name,
std::string  variable_name 
)

Definition at line 1317 of file NativeCodegen.cpp.

1319  {
1320  llvm::Value* result = nullptr;
1321  if (func == nullptr || variable_name.empty()) {
1322  return result;
1323  }
1324  bool is_found = false;
1325  for (auto bb_it = func->begin(); bb_it != func->end() && !is_found; ++bb_it) {
1326  if (!bb_name.empty() && bb_it->getName() != bb_name) {
1327  continue;
1328  }
1329  for (auto inst_it = bb_it->begin(); inst_it != bb_it->end(); inst_it++) {
1330  if (llvm::isa<InstType>(*inst_it)) {
1331  if (inst_it->getName() == variable_name) {
1332  result = &*inst_it;
1333  is_found = true;
1334  break;
1335  }
1336  }
1337  }
1338  }
1339  return result;
1340 }
std::string anonymous_namespace{NativeCodegen.cpp}::gen_array_any_all_sigs ( )

Definition at line 352 of file NativeCodegen.cpp.

References cpp_to_llvm_name(), and run_benchmark_import::result.

352  {
353  std::string result;
354  for (const std::string any_or_all : {"any", "all"}) {
355  for (const std::string elem_type :
356  {"int8_t", "int16_t", "int32_t", "int64_t", "float", "double"}) {
357  for (const std::string needle_type :
358  {"int8_t", "int16_t", "int32_t", "int64_t", "float", "double"}) {
359  for (const std::string op_name : {"eq", "ne", "lt", "le", "gt", "ge"}) {
360  result += ("declare i1 @array_" + any_or_all + "_" + op_name + "_" + elem_type +
361  "_" + needle_type + "(i8*, i64, " + cpp_to_llvm_name(needle_type) +
362  ", " + cpp_to_llvm_name(elem_type) + ");\n");
363  }
364  }
365  }
366  }
367  return result;
368 }
std::string cpp_to_llvm_name(const std::string &s)

+ Here is the call graph for this function:

std::string anonymous_namespace{NativeCodegen.cpp}::gen_translate_null_key_sigs ( )

Definition at line 370 of file NativeCodegen.cpp.

References cpp_to_llvm_name(), and run_benchmark_import::result.

370  {
371  std::string result;
372  for (const std::string key_type : {"int8_t", "int16_t", "int32_t", "int64_t"}) {
373  const auto key_llvm_type = cpp_to_llvm_name(key_type);
374  result += "declare i64 @translate_null_key_" + key_type + "(" + key_llvm_type + ", " +
375  key_llvm_type + ", i64);\n";
376  }
377  return result;
378 }
std::string cpp_to_llvm_name(const std::string &s)

+ Here is the call graph for this function:

std::vector<std::string> anonymous_namespace{NativeCodegen.cpp}::get_agg_fnames ( const std::vector< Analyzer::Expr * > &  target_exprs,
const bool  is_group_by 
)

Definition at line 1120 of file NativeCodegen.cpp.

1121  {
1122  std::vector<std::string> result;
1123  for (size_t target_idx = 0, agg_col_idx = 0; target_idx < target_exprs.size();
1124  ++target_idx, ++agg_col_idx) {
1125  const auto target_expr = target_exprs[target_idx];
1126  CHECK(target_expr);
1127  const auto target_type_info = target_expr->get_type_info();
1128  const auto agg_expr = dynamic_cast<Analyzer::AggExpr*>(target_expr);
1129  const bool is_varlen =
1130  (target_type_info.is_string() &&
1131  target_type_info.get_compression() == kENCODING_NONE) ||
1132  target_type_info.is_array(); // TODO: should it use is_varlen_array() ?
1133  if (!agg_expr || agg_expr->get_aggtype() == kSAMPLE) {
1134  result.emplace_back(target_type_info.is_fp() ? "agg_id_double" : "agg_id");
1135  if (is_varlen) {
1136  result.emplace_back("agg_id");
1137  }
1138  if (target_type_info.is_geometry()) {
1139  result.emplace_back("agg_id");
1140  for (auto i = 2; i < 2 * target_type_info.get_physical_coord_cols(); ++i) {
1141  result.emplace_back("agg_id");
1142  }
1143  }
1144  continue;
1145  }
1146  const auto agg_type = agg_expr->get_aggtype();
1147  const auto& agg_type_info =
1148  agg_type != kCOUNT ? agg_expr->get_arg()->get_type_info() : target_type_info;
1149  switch (agg_type) {
1150  case kAVG: {
1151  if (!agg_type_info.is_integer() && !agg_type_info.is_decimal() &&
1152  !agg_type_info.is_fp()) {
1153  throw std::runtime_error("AVG is only valid on integer and floating point");
1154  }
1155  result.emplace_back((agg_type_info.is_integer() || agg_type_info.is_time())
1156  ? "agg_sum"
1157  : "agg_sum_double");
1158  result.emplace_back((agg_type_info.is_integer() || agg_type_info.is_time())
1159  ? "agg_count"
1160  : "agg_count_double");
1161  break;
1162  }
1163  case kMIN: {
1164  if (agg_type_info.is_string() || agg_type_info.is_array() ||
1165  agg_type_info.is_geometry()) {
1166  throw std::runtime_error(
1167  "MIN on strings, arrays or geospatial types not supported yet");
1168  }
1169  result.emplace_back((agg_type_info.is_integer() || agg_type_info.is_time())
1170  ? "agg_min"
1171  : "agg_min_double");
1172  break;
1173  }
1174  case kMAX: {
1175  if (agg_type_info.is_string() || agg_type_info.is_array() ||
1176  agg_type_info.is_geometry()) {
1177  throw std::runtime_error(
1178  "MAX on strings, arrays or geospatial types not supported yet");
1179  }
1180  result.emplace_back((agg_type_info.is_integer() || agg_type_info.is_time())
1181  ? "agg_max"
1182  : "agg_max_double");
1183  break;
1184  }
1185  case kSUM: {
1186  if (!agg_type_info.is_integer() && !agg_type_info.is_decimal() &&
1187  !agg_type_info.is_fp()) {
1188  throw std::runtime_error("SUM is only valid on integer and floating point");
1189  }
1190  result.emplace_back((agg_type_info.is_integer() || agg_type_info.is_time())
1191  ? "agg_sum"
1192  : "agg_sum_double");
1193  break;
1194  }
1195  case kCOUNT:
1196  result.emplace_back(agg_expr->get_is_distinct() ? "agg_count_distinct"
1197  : "agg_count");
1198  break;
1199  case kSAMPLE: {
1200  // Note that varlen SAMPLE arguments are handled separately above
1201  result.emplace_back(agg_type_info.is_fp() ? "agg_id_double" : "agg_id");
1202  break;
1203  }
1205  result.emplace_back("agg_approximate_count_distinct");
1206  break;
1207  default:
1208  CHECK(false);
1209  }
1210  }
1211  return result;
1212 }
Definition: sqldefs.h:71
CHECK(cgen_state)
Definition: sqldefs.h:71
Definition: sqldefs.h:71
SQLAgg get_aggtype() const
Definition: Analyzer.h:1044
Definition: sqldefs.h:71
Definition: sqldefs.h:71
void anonymous_namespace{NativeCodegen.cpp}::optimize_ir ( llvm::Function *  query_func,
llvm::Module *  module,
const std::unordered_set< llvm::Function * > &  live_funcs,
const CompilationOptions co 
)

Definition at line 100 of file NativeCodegen.cpp.

References eliminate_dead_self_recursive_funcs(), LoopStrengthReduction, and CompilationOptions::opt_level_.

Referenced by CodeGenerator::generateNativeCPUCode().

103  {
104  llvm::legacy::PassManager pass_manager;
105 
106  pass_manager.add(llvm::createAlwaysInlinerLegacyPass());
107  pass_manager.add(llvm::createPromoteMemoryToRegisterPass());
108 #if LLVM_VERSION_MAJOR >= 7
109  pass_manager.add(llvm::createInstSimplifyLegacyPass());
110 #else
111  pass_manager.add(llvm::createInstructionSimplifierPass());
112 #endif
113  pass_manager.add(llvm::createInstructionCombiningPass());
114  pass_manager.add(llvm::createGlobalOptimizerPass());
115 
116  pass_manager.add(llvm::createLICMPass());
118  pass_manager.add(llvm::createLoopStrengthReducePass());
119  }
120  pass_manager.run(*module);
121 
123 }
std::unique_ptr< llvm::Module > module(runtime_module_shallow_copy(cgen_state))
void eliminate_dead_self_recursive_funcs(llvm::Module &M, const std::unordered_set< llvm::Function * > &live_funcs)
const ExecutorOptLevel opt_level_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void anonymous_namespace{NativeCodegen.cpp}::set_row_func_argnames ( llvm::Function *  row_func,
const size_t  in_col_count,
const size_t  agg_col_count,
const bool  hoist_literals 
)

Definition at line 971 of file NativeCodegen.cpp.

References kAVG, kCOUNT, kMAX, kMIN, and kSUM.

974  {
975  auto arg_it = row_func->arg_begin();
976 
977  if (agg_col_count) {
978  for (size_t i = 0; i < agg_col_count; ++i) {
979  arg_it->setName("out");
980  ++arg_it;
981  }
982  } else {
983  arg_it->setName("group_by_buff");
984  ++arg_it;
985  arg_it->setName("crt_matched");
986  ++arg_it;
987  arg_it->setName("total_matched");
988  ++arg_it;
989  arg_it->setName("old_total_matched");
990  ++arg_it;
991  arg_it->setName("max_matched");
992  ++arg_it;
993  }
994 
995  arg_it->setName("agg_init_val");
996  ++arg_it;
997 
998  arg_it->setName("pos");
999  ++arg_it;
1000 
1001  arg_it->setName("frag_row_off");
1002  ++arg_it;
1003 
1004  arg_it->setName("num_rows_per_scan");
1005  ++arg_it;
1006 
1007  if (hoist_literals) {
1008  arg_it->setName("literals");
1009  ++arg_it;
1010  }
1011 
1012  for (size_t i = 0; i < in_col_count; ++i) {
1013  arg_it->setName("col_buf" + std::to_string(i));
1014  ++arg_it;
1015  }
1016 
1017  arg_it->setName("join_hash_tables");
1018 }
const int64_t const uint32_t const uint32_t const uint32_t agg_col_count
std::string to_string(char const *&&v)

Variable Documentation

const std::string anonymous_namespace{NativeCodegen.cpp}::cuda_rt_decls

Definition at line 380 of file NativeCodegen.cpp.