OmniSciDB  0fdbebe030
 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 933 of file NativeCodegen.cpp.

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

936  {
937  for (auto it = llvm::inst_begin(query_func), e = llvm::inst_end(query_func); it != e;
938  ++it) {
939  if (!llvm::isa<llvm::CallInst>(*it)) {
940  continue;
941  }
942  auto& pos_call = llvm::cast<llvm::CallInst>(*it);
943  if (std::string(pos_call.getCalledFunction()->getName()) == pos_fn_name) {
944  if (use_resume_param) {
945  const auto error_code_arg = get_arg_by_name(query_func, "error_code");
946  llvm::ReplaceInstWithInst(
947  &pos_call,
948  llvm::CallInst::Create(module->getFunction(pos_fn_name + "_impl"),
949  error_code_arg));
950  } else {
951  llvm::ReplaceInstWithInst(
952  &pos_call,
953  llvm::CallInst::Create(module->getFunction(pos_fn_name + "_impl")));
954  }
955  break;
956  }
957  }
958 }
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 1083 of file NativeCodegen.cpp.

1086  {
1087  std::vector<llvm::CallInst*> query_stubs;
1088  for (auto it = llvm::inst_begin(multifrag_query_func),
1089  e = llvm::inst_end(multifrag_query_func);
1090  it != e;
1091  ++it) {
1092  if (!llvm::isa<llvm::CallInst>(*it)) {
1093  continue;
1094  }
1095  auto& query_call = llvm::cast<llvm::CallInst>(*it);
1096  if (std::string(query_call.getCalledFunction()->getName()) == query_fname) {
1097  query_stubs.push_back(&query_call);
1098  }
1099  }
1100  for (auto& S : query_stubs) {
1101  std::vector<llvm::Value*> args;
1102  for (size_t i = 0; i < S->getNumArgOperands(); ++i) {
1103  args.push_back(S->getArgOperand(i));
1104  }
1105  llvm::ReplaceInstWithInst(S, llvm::CallInst::Create(query_func, args, ""));
1106  }
1107 }
std::string anonymous_namespace{NativeCodegen.cpp}::cpp_to_llvm_name ( const std::string &  s)

Definition at line 327 of file NativeCodegen.cpp.

References CHECK().

Referenced by gen_array_any_all_sigs(), and gen_translate_null_key_sigs().

327  {
328  if (s == "int8_t") {
329  return "i8";
330  }
331  if (s == "int16_t") {
332  return "i16";
333  }
334  if (s == "int32_t") {
335  return "i32";
336  }
337  if (s == "int64_t") {
338  return "i64";
339  }
340  CHECK(s == "float" || s == "double");
341  return s;
342 }
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 1009 of file NativeCodegen.cpp.

1015  {
1016  std::vector<llvm::Type*> row_process_arg_types;
1017 
1018  if (agg_col_count) {
1019  // output (aggregate) arguments
1020  for (size_t i = 0; i < agg_col_count; ++i) {
1021  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1022  }
1023  } else {
1024  // group by buffer
1025  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1026  // current match count
1027  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1028  // total match count passed from the caller
1029  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1030  // old total match count returned to the caller
1031  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1032  // max matched (total number of slots in the output buffer)
1033  row_process_arg_types.push_back(llvm::Type::getInt32PtrTy(context));
1034  }
1035 
1036  // aggregate init values
1037  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1038 
1039  // position argument
1040  row_process_arg_types.push_back(llvm::Type::getInt64Ty(context));
1041 
1042  // fragment row offset argument
1043  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1044 
1045  // number of rows for each scan
1046  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1047 
1048  // literals buffer argument
1049  if (hoist_literals) {
1050  row_process_arg_types.push_back(llvm::Type::getInt8PtrTy(context));
1051  }
1052 
1053  // Generate the function signature and column head fetches s.t.
1054  // double indirection isn't needed in the inner loop
1055  auto& fetch_bb = query_func->front();
1056  llvm::IRBuilder<> fetch_ir_builder(&fetch_bb);
1057  fetch_ir_builder.SetInsertPoint(&*fetch_bb.begin());
1058  auto col_heads = generate_column_heads_load(
1059  in_col_count, query_func->args().begin(), fetch_ir_builder, context);
1060  CHECK_EQ(in_col_count, col_heads.size());
1061 
1062  // column buffer arguments
1063  for (size_t i = 0; i < in_col_count; ++i) {
1064  row_process_arg_types.emplace_back(llvm::Type::getInt8PtrTy(context));
1065  }
1066 
1067  // join hash table argument
1068  row_process_arg_types.push_back(llvm::Type::getInt64PtrTy(context));
1069 
1070  // generate the function
1071  auto ft =
1072  llvm::FunctionType::get(get_int_type(32, context), row_process_arg_types, false);
1073 
1074  auto row_func =
1075  llvm::Function::Create(ft, llvm::Function::ExternalLinkage, "row_func", module);
1076 
1077  // set the row function argument names; for debugging purposes only
1078  set_row_func_argnames(row_func, in_col_count, agg_col_count, hoist_literals);
1079 
1080  return std::make_pair(row_func, col_heads);
1081 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
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 76 of file NativeCodegen.cpp.

Referenced by optimize_ir().

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

+ 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 1310 of file NativeCodegen.cpp.

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

Definition at line 344 of file NativeCodegen.cpp.

References cpp_to_llvm_name(), and run_benchmark_import::result.

344  {
345  std::string result;
346  for (const std::string any_or_all : {"any", "all"}) {
347  for (const std::string elem_type :
348  {"int8_t", "int16_t", "int32_t", "int64_t", "float", "double"}) {
349  for (const std::string needle_type :
350  {"int8_t", "int16_t", "int32_t", "int64_t", "float", "double"}) {
351  for (const std::string op_name : {"eq", "ne", "lt", "le", "gt", "ge"}) {
352  result += ("declare i1 @array_" + any_or_all + "_" + op_name + "_" + elem_type +
353  "_" + needle_type + "(i8*, i64, " + cpp_to_llvm_name(needle_type) +
354  ", " + cpp_to_llvm_name(elem_type) + ");\n");
355  }
356  }
357  }
358  }
359  return result;
360 }
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 362 of file NativeCodegen.cpp.

References cpp_to_llvm_name(), and run_benchmark_import::result.

362  {
363  std::string result;
364  for (const std::string key_type : {"int8_t", "int16_t", "int32_t", "int64_t"}) {
365  const auto key_llvm_type = cpp_to_llvm_name(key_type);
366  result += "declare i64 @translate_null_key_" + key_type + "(" + key_llvm_type + ", " +
367  key_llvm_type + ", i64);\n";
368  }
369  return result;
370 }
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 1109 of file NativeCodegen.cpp.

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

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

Referenced by CodeGenerator::generateNativeCPUCode().

104  {
105  llvm::legacy::PassManager pass_manager;
106 
107  pass_manager.add(llvm::createAlwaysInlinerLegacyPass());
108  pass_manager.add(llvm::createPromoteMemoryToRegisterPass());
109 #if LLVM_VERSION_MAJOR >= 7
110  pass_manager.add(llvm::createInstSimplifyLegacyPass());
111 #else
112  pass_manager.add(llvm::createInstructionSimplifierPass());
113 #endif
114  pass_manager.add(llvm::createInstructionCombiningPass());
115  pass_manager.add(llvm::createGlobalOptimizerPass());
116 
117  pass_manager.add(llvm::createLICMPass());
119  pass_manager.add(llvm::createLoopStrengthReducePass());
120  }
121  pass_manager.run(*module);
122 
124 }
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)
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 960 of file NativeCodegen.cpp.

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

963  {
964  auto arg_it = row_func->arg_begin();
965 
966  if (agg_col_count) {
967  for (size_t i = 0; i < agg_col_count; ++i) {
968  arg_it->setName("out");
969  ++arg_it;
970  }
971  } else {
972  arg_it->setName("group_by_buff");
973  ++arg_it;
974  arg_it->setName("crt_matched");
975  ++arg_it;
976  arg_it->setName("total_matched");
977  ++arg_it;
978  arg_it->setName("old_total_matched");
979  ++arg_it;
980  arg_it->setName("max_matched");
981  ++arg_it;
982  }
983 
984  arg_it->setName("agg_init_val");
985  ++arg_it;
986 
987  arg_it->setName("pos");
988  ++arg_it;
989 
990  arg_it->setName("frag_row_off");
991  ++arg_it;
992 
993  arg_it->setName("num_rows_per_scan");
994  ++arg_it;
995 
996  if (hoist_literals) {
997  arg_it->setName("literals");
998  ++arg_it;
999  }
1000 
1001  for (size_t i = 0; i < in_col_count; ++i) {
1002  arg_it->setName("col_buf" + std::to_string(i));
1003  ++arg_it;
1004  }
1005 
1006  arg_it->setName("join_hash_tables");
1007 }
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 372 of file NativeCodegen.cpp.