OmniSciDB  5ade3759e0
IRCodegen.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "../Parser/ParserNode.h"
18 #include "CodeGenerator.h"
19 #include "Execute.h"
20 #include "MaxwellCodegenPatch.h"
21 #include "RelAlgTranslator.h"
22 
23 // Driver methods for the IR generation.
24 
25 std::vector<llvm::Value*> CodeGenerator::codegen(const Analyzer::Expr* expr,
26  const bool fetch_columns,
27  const CompilationOptions& co) {
28  if (!expr) {
29  return {posArg(expr)};
30  }
31  auto bin_oper = dynamic_cast<const Analyzer::BinOper*>(expr);
32  if (bin_oper) {
33  return {codegen(bin_oper, co)};
34  }
35  auto u_oper = dynamic_cast<const Analyzer::UOper*>(expr);
36  if (u_oper) {
37  return {codegen(u_oper, co)};
38  }
39  auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(expr);
40  if (col_var) {
41  return codegenColumn(col_var, fetch_columns, co);
42  }
43  auto constant = dynamic_cast<const Analyzer::Constant*>(expr);
44  if (constant) {
45  if (constant->get_is_null()) {
46  const auto& ti = constant->get_type_info();
47  return {ti.is_fp()
48  ? static_cast<llvm::Value*>(executor_->cgen_state_->inlineFpNull(ti))
49  : static_cast<llvm::Value*>(executor_->cgen_state_->inlineIntNull(ti))};
50  }
51  // The dictionary encoding case should be handled by the parent expression
52  // (cast, for now), here is too late to know the dictionary id
53  CHECK_NE(kENCODING_DICT, constant->get_type_info().get_compression());
54  return {codegen(constant, constant->get_type_info().get_compression(), 0, co)};
55  }
56  auto case_expr = dynamic_cast<const Analyzer::CaseExpr*>(expr);
57  if (case_expr) {
58  return {codegen(case_expr, co)};
59  }
60  auto extract_expr = dynamic_cast<const Analyzer::ExtractExpr*>(expr);
61  if (extract_expr) {
62  return {codegen(extract_expr, co)};
63  }
64  auto dateadd_expr = dynamic_cast<const Analyzer::DateaddExpr*>(expr);
65  if (dateadd_expr) {
66  return {codegen(dateadd_expr, co)};
67  }
68  auto datediff_expr = dynamic_cast<const Analyzer::DatediffExpr*>(expr);
69  if (datediff_expr) {
70  return {codegen(datediff_expr, co)};
71  }
72  auto datetrunc_expr = dynamic_cast<const Analyzer::DatetruncExpr*>(expr);
73  if (datetrunc_expr) {
74  return {codegen(datetrunc_expr, co)};
75  }
76  auto charlength_expr = dynamic_cast<const Analyzer::CharLengthExpr*>(expr);
77  if (charlength_expr) {
78  return {codegen(charlength_expr, co)};
79  }
80  auto keyforstring_expr = dynamic_cast<const Analyzer::KeyForStringExpr*>(expr);
81  if (keyforstring_expr) {
82  return {codegen(keyforstring_expr, co)};
83  }
84  auto cardinality_expr = dynamic_cast<const Analyzer::CardinalityExpr*>(expr);
85  if (cardinality_expr) {
86  return {codegen(cardinality_expr, co)};
87  }
88  auto like_expr = dynamic_cast<const Analyzer::LikeExpr*>(expr);
89  if (like_expr) {
90  return {codegen(like_expr, co)};
91  }
92  auto regexp_expr = dynamic_cast<const Analyzer::RegexpExpr*>(expr);
93  if (regexp_expr) {
94  return {codegen(regexp_expr, co)};
95  }
96  auto likelihood_expr = dynamic_cast<const Analyzer::LikelihoodExpr*>(expr);
97  if (likelihood_expr) {
98  return {codegen(likelihood_expr->get_arg(), fetch_columns, co)};
99  }
100  auto in_expr = dynamic_cast<const Analyzer::InValues*>(expr);
101  if (in_expr) {
102  return {codegen(in_expr, co)};
103  }
104  auto in_integer_set_expr = dynamic_cast<const Analyzer::InIntegerSet*>(expr);
105  if (in_integer_set_expr) {
106  return {codegen(in_integer_set_expr, co)};
107  }
108  auto function_oper_with_custom_type_handling_expr =
109  dynamic_cast<const Analyzer::FunctionOperWithCustomTypeHandling*>(expr);
110  if (function_oper_with_custom_type_handling_expr) {
112  function_oper_with_custom_type_handling_expr, co)};
113  }
114  auto array_oper_expr = dynamic_cast<const Analyzer::ArrayExpr*>(expr);
115  if (array_oper_expr) {
116  return {codegenArrayExpr(array_oper_expr, co)};
117  }
118  auto function_oper_expr = dynamic_cast<const Analyzer::FunctionOper*>(expr);
119  if (function_oper_expr) {
120  return {codegenFunctionOper(function_oper_expr, co)};
121  }
122  if (dynamic_cast<const Analyzer::OffsetInFragment*>(expr)) {
123  return {posArg(nullptr)};
124  }
125  if (dynamic_cast<const Analyzer::WindowFunction*>(expr)) {
126  throw std::runtime_error("Window expression not supported in this context");
127  }
128  abort();
129 }
130 
131 llvm::Value* CodeGenerator::codegen(const Analyzer::BinOper* bin_oper,
132  const CompilationOptions& co) {
133  const auto optype = bin_oper->get_optype();
134  if (IS_ARITHMETIC(optype)) {
135  return codegenArith(bin_oper, co);
136  }
137  if (IS_COMPARISON(optype)) {
138  return codegenCmp(bin_oper, co);
139  }
140  if (IS_LOGIC(optype)) {
141  return codegenLogical(bin_oper, co);
142  }
143  if (optype == kARRAY_AT) {
144  return codegenArrayAt(bin_oper, co);
145  }
146  abort();
147 }
148 
149 llvm::Value* CodeGenerator::codegen(const Analyzer::UOper* u_oper,
150  const CompilationOptions& co) {
151  const auto optype = u_oper->get_optype();
152  switch (optype) {
153  case kNOT: {
154  return codegenLogical(u_oper, co);
155  }
156  case kCAST: {
157  return codegenCast(u_oper, co);
158  }
159  case kUMINUS: {
160  return codegenUMinus(u_oper, co);
161  }
162  case kISNULL: {
163  return codegenIsNull(u_oper, co);
164  }
165  case kUNNEST:
166  return codegenUnnest(u_oper, co);
167  default:
168  abort();
169  }
170 }
171 
172 namespace {
173 
175  const std::shared_ptr<Analyzer::Expr>& qual) {
176  const auto qual_cf = qual_to_conjunctive_form(qual);
177  ra_exe_unit.simple_quals.insert(ra_exe_unit.simple_quals.end(),
178  qual_cf.simple_quals.begin(),
179  qual_cf.simple_quals.end());
180  ra_exe_unit.quals.insert(
181  ra_exe_unit.quals.end(), qual_cf.quals.begin(), qual_cf.quals.end());
182 }
183 
185  const ExecutionOptions& eo,
186  const std::vector<InputTableInfo>& query_infos,
187  const size_t level_idx,
188  const std::string& fail_reason) {
189  if (eo.allow_loop_joins) {
190  return;
191  }
192  if (level_idx + 1 != ra_exe_unit.join_quals.size()) {
193  throw std::runtime_error(
194  "Hash join failed, reason(s): " + fail_reason +
195  " | Cannot fall back to loop join for intermediate join quals");
196  }
197  if (!is_trivial_loop_join(query_infos, ra_exe_unit)) {
198  throw std::runtime_error(
199  "Hash join failed, reason(s): " + fail_reason +
200  " | Cannot fall back to loop join for non-trivial inner table size");
201  }
202 }
203 
204 } // namespace
205 
206 std::vector<JoinLoop> Executor::buildJoinLoops(
207  RelAlgExecutionUnit& ra_exe_unit,
208  const CompilationOptions& co,
209  const ExecutionOptions& eo,
210  const std::vector<InputTableInfo>& query_infos,
211  ColumnCacheMap& column_cache) {
212  INJECT_TIMER(buildJoinLoops);
213  std::vector<JoinLoop> join_loops;
214  for (size_t level_idx = 0, current_hash_table_idx = 0;
215  level_idx < ra_exe_unit.join_quals.size();
216  ++level_idx) {
217  const auto& current_level_join_conditions = ra_exe_unit.join_quals[level_idx];
218  std::vector<std::string> fail_reasons;
219  const auto current_level_hash_table =
220  buildCurrentLevelHashTable(current_level_join_conditions,
221  ra_exe_unit,
222  co,
223  query_infos,
224  column_cache,
225  fail_reasons);
226  const auto found_outer_join_matches_cb =
227  [this, level_idx](llvm::Value* found_outer_join_matches) {
231  found_outer_join_matches;
232  };
233  const auto is_deleted_cb = buildIsDeletedCb(ra_exe_unit, level_idx, co);
234  if (current_level_hash_table) {
235  if (current_level_hash_table->getHashType() == JoinHashTable::HashType::OneToOne) {
236  join_loops.emplace_back(
238  current_level_join_conditions.type,
239  [this, current_hash_table_idx, level_idx, current_level_hash_table, &co](
240  const std::vector<llvm::Value*>& prev_iters) {
241  addJoinLoopIterator(prev_iters, level_idx);
242  JoinLoopDomain domain{{0}};
243  domain.slot_lookup_result =
244  current_level_hash_table->codegenSlot(co, current_hash_table_idx);
245  return domain;
246  },
247  nullptr,
248  current_level_join_conditions.type == JoinType::LEFT
249  ? std::function<void(llvm::Value*)>(found_outer_join_matches_cb)
250  : nullptr,
251  is_deleted_cb);
252  } else {
253  join_loops.emplace_back(
255  current_level_join_conditions.type,
256  [this, current_hash_table_idx, level_idx, current_level_hash_table, &co](
257  const std::vector<llvm::Value*>& prev_iters) {
258  addJoinLoopIterator(prev_iters, level_idx);
259  JoinLoopDomain domain{{0}};
260  const auto matching_set = current_level_hash_table->codegenMatchingSet(
261  co, current_hash_table_idx);
262  domain.values_buffer = matching_set.elements;
263  domain.element_count = matching_set.count;
264  return domain;
265  },
266  nullptr,
267  current_level_join_conditions.type == JoinType::LEFT
268  ? std::function<void(llvm::Value*)>(found_outer_join_matches_cb)
269  : nullptr,
270  is_deleted_cb);
271  }
272  ++current_hash_table_idx;
273  } else {
274  const auto fail_reasons_str = current_level_join_conditions.quals.empty()
275  ? "No equijoin expression found"
276  : boost::algorithm::join(fail_reasons, " | ");
278  ra_exe_unit, eo, query_infos, level_idx, fail_reasons_str);
279  // Callback provided to the `JoinLoop` framework to evaluate the (outer) join
280  // condition.
281  VLOG(1) << "Unable to build hash table, falling back to loop join: "
282  << fail_reasons_str;
283  const auto outer_join_condition_cb =
284  [this, level_idx, &co, &current_level_join_conditions](
285  const std::vector<llvm::Value*>& prev_iters) {
286  // The values generated for the match path don't dominate all uses
287  // since on the non-match path nulls are generated. Reset the cache
288  // once the condition is generated to avoid incorrect reuse.
289  FetchCacheAnchor anchor(cgen_state_.get());
290  addJoinLoopIterator(prev_iters, level_idx + 1);
291  llvm::Value* left_join_cond = cgen_state_->llBool(true);
292  CodeGenerator code_generator(this);
293  for (auto expr : current_level_join_conditions.quals) {
294  left_join_cond = cgen_state_->ir_builder_.CreateAnd(
295  left_join_cond,
296  code_generator.toBool(
297  code_generator.codegen(expr.get(), true, co).front()));
298  }
299  return left_join_cond;
300  };
301  join_loops.emplace_back(
303  current_level_join_conditions.type,
304  [this, level_idx](const std::vector<llvm::Value*>& prev_iters) {
305  addJoinLoopIterator(prev_iters, level_idx);
306  JoinLoopDomain domain{{0}};
307  const auto rows_per_scan_ptr = cgen_state_->ir_builder_.CreateGEP(
308  get_arg_by_name(cgen_state_->row_func_, "num_rows_per_scan"),
309  cgen_state_->llInt(int32_t(level_idx + 1)));
310  domain.upper_bound = cgen_state_->ir_builder_.CreateLoad(rows_per_scan_ptr,
311  "num_rows_per_scan");
312  return domain;
313  },
314  current_level_join_conditions.type == JoinType::LEFT
315  ? std::function<llvm::Value*(const std::vector<llvm::Value*>&)>(
316  outer_join_condition_cb)
317  : nullptr,
318  current_level_join_conditions.type == JoinType::LEFT
319  ? std::function<void(llvm::Value*)>(found_outer_join_matches_cb)
320  : nullptr,
321  is_deleted_cb);
322  }
323  }
324  return join_loops;
325 }
326 
327 std::function<llvm::Value*(const std::vector<llvm::Value*>&, llvm::Value*)>
329  const size_t level_idx,
330  const CompilationOptions& co) {
331  CHECK_LT(level_idx + 1, ra_exe_unit.input_descs.size());
332  const auto input_desc = ra_exe_unit.input_descs[level_idx + 1];
333  if (input_desc.getSourceType() != InputSourceType::TABLE) {
334  return nullptr;
335  }
336  const auto td = catalog_->getMetadataForTable(input_desc.getTableId());
337  CHECK(td);
338  const auto deleted_cd = catalog_->getDeletedColumnIfRowsDeleted(td);
339  if (!deleted_cd) {
340  return nullptr;
341  }
342  CHECK(deleted_cd->columnType.is_boolean());
343  const auto deleted_expr = makeExpr<Analyzer::ColumnVar>(deleted_cd->columnType,
344  input_desc.getTableId(),
345  deleted_cd->columnId,
346  input_desc.getNestLevel());
347  return [this, deleted_expr, level_idx, &co](const std::vector<llvm::Value*>& prev_iters,
348  llvm::Value* have_more_inner_rows) {
349  const auto matching_row_index = addJoinLoopIterator(prev_iters, level_idx + 1);
350  // Avoid fetching the deleted column from a position which is not valid.
351  // An invalid position can be returned by a one to one hash lookup (negative)
352  // or at the end of iteration over a set of matching values.
353  llvm::Value* is_valid_it{nullptr};
354  if (have_more_inner_rows) {
355  is_valid_it = have_more_inner_rows;
356  } else {
357  is_valid_it = cgen_state_->ir_builder_.CreateICmp(
358  llvm::ICmpInst::ICMP_SGE, matching_row_index, cgen_state_->llInt<int64_t>(0));
359  }
360  const auto it_valid_bb = llvm::BasicBlock::Create(
361  cgen_state_->context_, "it_valid", cgen_state_->row_func_);
362  const auto it_not_valid_bb = llvm::BasicBlock::Create(
363  cgen_state_->context_, "it_not_valid", cgen_state_->row_func_);
364  cgen_state_->ir_builder_.CreateCondBr(is_valid_it, it_valid_bb, it_not_valid_bb);
365  const auto row_is_deleted_bb = llvm::BasicBlock::Create(
366  cgen_state_->context_, "row_is_deleted", cgen_state_->row_func_);
367  cgen_state_->ir_builder_.SetInsertPoint(it_valid_bb);
368  CodeGenerator code_generator(this);
369  const auto row_is_deleted = code_generator.toBool(
370  code_generator.codegen(deleted_expr.get(), true, co).front());
371  cgen_state_->ir_builder_.CreateBr(row_is_deleted_bb);
372  cgen_state_->ir_builder_.SetInsertPoint(it_not_valid_bb);
373  const auto row_is_deleted_default = cgen_state_->llBool(false);
374  cgen_state_->ir_builder_.CreateBr(row_is_deleted_bb);
375  cgen_state_->ir_builder_.SetInsertPoint(row_is_deleted_bb);
376  auto row_is_deleted_or_default =
377  cgen_state_->ir_builder_.CreatePHI(row_is_deleted->getType(), 2);
378  row_is_deleted_or_default->addIncoming(row_is_deleted, it_valid_bb);
379  row_is_deleted_or_default->addIncoming(row_is_deleted_default, it_not_valid_bb);
380  return row_is_deleted_or_default;
381  };
382 }
383 
384 std::shared_ptr<JoinHashTableInterface> Executor::buildCurrentLevelHashTable(
385  const JoinCondition& current_level_join_conditions,
386  RelAlgExecutionUnit& ra_exe_unit,
387  const CompilationOptions& co,
388  const std::vector<InputTableInfo>& query_infos,
389  ColumnCacheMap& column_cache,
390  std::vector<std::string>& fail_reasons) {
391  if (current_level_join_conditions.type != JoinType::INNER &&
392  current_level_join_conditions.quals.size() > 1) {
393  fail_reasons.emplace_back("No equijoin expression found for outer join");
394  return nullptr;
395  }
396  std::shared_ptr<JoinHashTableInterface> current_level_hash_table;
397  for (const auto& join_qual : current_level_join_conditions.quals) {
398  auto qual_bin_oper = std::dynamic_pointer_cast<Analyzer::BinOper>(join_qual);
399  if (!qual_bin_oper || !IS_EQUIVALENCE(qual_bin_oper->get_optype())) {
400  fail_reasons.emplace_back("No equijoin expression found");
401  if (current_level_join_conditions.type == JoinType::INNER) {
402  add_qualifier_to_execution_unit(ra_exe_unit, join_qual);
403  }
404  continue;
405  }
406  JoinHashTableOrError hash_table_or_error;
407  if (!current_level_hash_table) {
408  hash_table_or_error = buildHashTableForQualifier(
409  qual_bin_oper,
410  query_infos,
414  column_cache);
415  current_level_hash_table = hash_table_or_error.hash_table;
416  }
417  if (hash_table_or_error.hash_table) {
418  plan_state_->join_info_.join_hash_tables_.push_back(hash_table_or_error.hash_table);
419  plan_state_->join_info_.equi_join_tautologies_.push_back(qual_bin_oper);
420  } else {
421  fail_reasons.push_back(hash_table_or_error.fail_reason);
422  if (current_level_join_conditions.type == JoinType::INNER) {
423  add_qualifier_to_execution_unit(ra_exe_unit, qual_bin_oper);
424  }
425  }
426  }
427  return current_level_hash_table;
428 }
429 
430 llvm::Value* Executor::addJoinLoopIterator(const std::vector<llvm::Value*>& prev_iters,
431  const size_t level_idx) {
432  // Iterators are added for loop-outer joins when the head of the loop is generated,
433  // then once again when the body if generated. Allow this instead of special handling
434  // of call sites.
435  const auto it = cgen_state_->scan_idx_to_hash_pos_.find(level_idx);
436  if (it != cgen_state_->scan_idx_to_hash_pos_.end()) {
437  return it->second;
438  }
439  CHECK(!prev_iters.empty());
440  llvm::Value* matching_row_index = prev_iters.back();
441  const auto it_ok =
442  cgen_state_->scan_idx_to_hash_pos_.emplace(level_idx, matching_row_index);
443  CHECK(it_ok.second);
444  return matching_row_index;
445 }
446 
447 void Executor::codegenJoinLoops(const std::vector<JoinLoop>& join_loops,
448  const RelAlgExecutionUnit& ra_exe_unit,
449  GroupByAndAggregate& group_by_and_aggregate,
450  llvm::Function* query_func,
451  llvm::BasicBlock* entry_bb,
452  const QueryMemoryDescriptor& query_mem_desc,
453  const CompilationOptions& co,
454  const ExecutionOptions& eo) {
455  const auto exit_bb =
456  llvm::BasicBlock::Create(cgen_state_->context_, "exit", cgen_state_->row_func_);
457  cgen_state_->ir_builder_.SetInsertPoint(exit_bb);
458  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt<int32_t>(0));
459  cgen_state_->ir_builder_.SetInsertPoint(entry_bb);
460  CodeGenerator code_generator(this);
461  const auto loops_entry_bb = JoinLoop::codegen(
462  join_loops,
463  [this,
464  query_func,
465  &query_mem_desc,
466  &co,
467  &eo,
468  &group_by_and_aggregate,
469  &join_loops,
470  &ra_exe_unit](const std::vector<llvm::Value*>& prev_iters) {
471  addJoinLoopIterator(prev_iters, join_loops.size());
472  auto& builder = cgen_state_->ir_builder_;
473  const auto loop_body_bb = llvm::BasicBlock::Create(
474  builder.getContext(), "loop_body", builder.GetInsertBlock()->getParent());
475  builder.SetInsertPoint(loop_body_bb);
476  const bool can_return_error =
477  compileBody(ra_exe_unit, group_by_and_aggregate, query_mem_desc, co);
478  if (can_return_error || cgen_state_->needs_error_check_ ||
480  createErrorCheckControlFlow(
481  query_func, eo.with_dynamic_watchdog, co.device_type_);
482  }
483  return loop_body_bb;
484  },
485  code_generator.posArg(nullptr),
486  exit_bb,
488  cgen_state_->ir_builder_.SetInsertPoint(entry_bb);
489  cgen_state_->ir_builder_.CreateBr(loops_entry_bb);
490 }
491 
493  Analyzer::Expr* group_by_col,
494  const size_t col_width,
495  const CompilationOptions& co,
496  const bool translate_null_val,
497  const int64_t translated_null_val,
498  GroupByAndAggregate::DiamondCodegen& diamond_codegen,
499  std::stack<llvm::BasicBlock*>& array_loops,
500  const bool thread_mem_shared) {
501  CHECK_GE(col_width, sizeof(int32_t));
502  CodeGenerator code_generator(this);
503  auto group_key = code_generator.codegen(group_by_col, true, co).front();
504  auto key_to_cache = group_key;
505  if (dynamic_cast<Analyzer::UOper*>(group_by_col) &&
506  static_cast<Analyzer::UOper*>(group_by_col)->get_optype() == kUNNEST) {
507  auto preheader = cgen_state_->ir_builder_.GetInsertBlock();
508  auto array_loop_head = llvm::BasicBlock::Create(cgen_state_->context_,
509  "array_loop_head",
511  preheader->getNextNode());
512  diamond_codegen.setFalseTarget(array_loop_head);
513  const auto ret_ty = get_int_type(32, cgen_state_->context_);
514  auto array_idx_ptr = cgen_state_->ir_builder_.CreateAlloca(ret_ty);
515  CHECK(array_idx_ptr);
516  cgen_state_->ir_builder_.CreateStore(cgen_state_->llInt(int32_t(0)), array_idx_ptr);
517  const auto arr_expr = static_cast<Analyzer::UOper*>(group_by_col)->get_operand();
518  const auto& array_ti = arr_expr->get_type_info();
519  CHECK(array_ti.is_array());
520  const auto& elem_ti = array_ti.get_elem_type();
521  auto array_len =
522  (array_ti.get_size() > 0)
523  ? cgen_state_->llInt(array_ti.get_size() / elem_ti.get_size())
525  "array_size",
526  ret_ty,
527  {group_key,
528  code_generator.posArg(arr_expr),
529  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
530  cgen_state_->ir_builder_.CreateBr(array_loop_head);
531  cgen_state_->ir_builder_.SetInsertPoint(array_loop_head);
532  CHECK(array_len);
533  auto array_idx = cgen_state_->ir_builder_.CreateLoad(array_idx_ptr);
534  auto bound_check = cgen_state_->ir_builder_.CreateICmp(
535  llvm::ICmpInst::ICMP_SLT, array_idx, array_len);
536  auto array_loop_body = llvm::BasicBlock::Create(
537  cgen_state_->context_, "array_loop_body", cgen_state_->row_func_);
538  cgen_state_->ir_builder_.CreateCondBr(
539  bound_check,
540  array_loop_body,
541  array_loops.empty() ? diamond_codegen.orig_cond_false_ : array_loops.top());
542  cgen_state_->ir_builder_.SetInsertPoint(array_loop_body);
543  cgen_state_->ir_builder_.CreateStore(
544  cgen_state_->ir_builder_.CreateAdd(array_idx, cgen_state_->llInt(int32_t(1))),
545  array_idx_ptr);
546  auto array_at_fname = "array_at_" + numeric_type_name(elem_ti);
547  if (array_ti.get_size() < 0) {
548  if (array_ti.get_notnull()) {
549  array_at_fname = "notnull_" + array_at_fname;
550  }
551  array_at_fname = "varlen_" + array_at_fname;
552  }
553  const auto ar_ret_ty =
554  elem_ti.is_fp()
555  ? (elem_ti.get_type() == kDOUBLE
556  ? llvm::Type::getDoubleTy(cgen_state_->context_)
557  : llvm::Type::getFloatTy(cgen_state_->context_))
558  : get_int_type(elem_ti.get_logical_size() * 8, cgen_state_->context_);
559  group_key = cgen_state_->emitExternalCall(
560  array_at_fname,
561  ar_ret_ty,
562  {group_key, code_generator.posArg(arr_expr), array_idx});
564  elem_ti, isArchMaxwell(co.device_type_), thread_mem_shared)) {
565  key_to_cache = spillDoubleElement(group_key, ar_ret_ty);
566  } else {
567  key_to_cache = group_key;
568  }
569  CHECK(array_loop_head);
570  array_loops.push(array_loop_head);
571  }
572  cgen_state_->group_by_expr_cache_.push_back(key_to_cache);
573  llvm::Value* orig_group_key{nullptr};
574  if (translate_null_val) {
575  const std::string translator_func_name(
576  col_width == sizeof(int32_t) ? "translate_null_key_i32_" : "translate_null_key_");
577  const auto& ti = group_by_col->get_type_info();
578  const auto key_type = get_int_type(ti.get_logical_size() * 8, cgen_state_->context_);
579  orig_group_key = group_key;
580  group_key = cgen_state_->emitCall(
581  translator_func_name + numeric_type_name(ti),
582  {group_key,
583  static_cast<llvm::Value*>(
584  llvm::ConstantInt::get(key_type, inline_int_null_val(ti))),
585  static_cast<llvm::Value*>(llvm::ConstantInt::get(
586  llvm::Type::getInt64Ty(cgen_state_->context_), translated_null_val))});
587  }
588  group_key = cgen_state_->ir_builder_.CreateBitCast(
589  cgen_state_->castToTypeIn(group_key, col_width * 8),
590  get_int_type(col_width * 8, cgen_state_->context_));
591  if (orig_group_key) {
592  orig_group_key = cgen_state_->ir_builder_.CreateBitCast(
593  cgen_state_->castToTypeIn(orig_group_key, col_width * 8),
594  get_int_type(col_width * 8, cgen_state_->context_));
595  }
596  return {group_key, orig_group_key};
597 }
JoinInfo join_info_
Definition: PlanState.h:56
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:103
#define IS_LOGIC(X)
Definition: sqldefs.h:60
std::vector< llvm::Value * > outer_join_match_found_per_level_
Definition: CgenState.h:279
bool is_fp() const
Definition: sqltypes.h:454
bool is_trivial_loop_join(const std::vector< InputTableInfo > &query_infos, const RelAlgExecutionUnit &ra_exe_unit)
Definition: Execute.cpp:1054
void codegenJoinLoops(const std::vector< JoinLoop > &join_loops, const RelAlgExecutionUnit &ra_exe_unit, GroupByAndAggregate &group_by_and_aggregate, llvm::Function *query_func, llvm::BasicBlock *entry_bb, const QueryMemoryDescriptor &query_mem_desc, const CompilationOptions &co, const ExecutionOptions &eo)
Definition: IRCodegen.cpp:447
#define IS_EQUIVALENCE(X)
Definition: sqldefs.h:67
llvm::Value * codegenArith(const Analyzer::BinOper *, const CompilationOptions &)
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:268
std::string join(T const &container, std::string const &delim)
#define CHECK_GE(x, y)
Definition: Logger.h:200
bool need_patch_unnest_double(const SQLTypeInfo &ti, const bool is_maxwell, const bool mem_shared)
GroupColLLVMValue groupByColumnCodegen(Analyzer::Expr *group_by_col, const size_t col_width, const CompilationOptions &, const bool translate_null_val, const int64_t translated_null_val, GroupByAndAggregate::DiamondCodegen &, std::stack< llvm::BasicBlock *> &, const bool thread_mem_shared)
Definition: IRCodegen.cpp:492
Definition: sqldefs.h:49
virtual std::vector< llvm::Value * > codegenColumn(const Analyzer::ColumnVar *, const bool fetch_column, const CompilationOptions &)
Definition: ColumnIR.cpp:92
llvm::Value * codegenArrayAt(const Analyzer::BinOper *, const CompilationOptions &)
Definition: ArrayIR.cpp:25
QualsConjunctiveForm qual_to_conjunctive_form(const std::shared_ptr< Analyzer::Expr > qual_expr)
const std::vector< InputDescriptor > input_descs
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
static llvm::BasicBlock * codegen(const std::vector< JoinLoop > &join_loops, const std::function< llvm::BasicBlock *(const std::vector< llvm::Value *> &)> &body_codegen, llvm::Value *outer_iter, llvm::BasicBlock *exit_bb, llvm::IRBuilder<> &builder)
Definition: JoinLoop.cpp:45
llvm::Function * row_func_
Definition: CgenState.h:264
SQLOps get_optype() const
Definition: Analyzer.h:432
llvm::Value * codegenIsNull(const Analyzer::UOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:368
llvm::ConstantInt * llBool(const bool v) const
Definition: CgenState.h:261
std::vector< llvm::Value * > group_by_expr_cache_
Definition: CgenState.h:275
llvm::LLVMContext & context_
Definition: CgenState.h:266
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:114
#define INJECT_TIMER(DESC)
Definition: measure.h:91
#define CHECK_NE(x, y)
Definition: Logger.h:196
const bool with_dynamic_watchdog
const JoinQualsPerNestingLevel join_quals
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value *> args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={})
Definition: CgenState.h:203
void setFalseTarget(llvm::BasicBlock *cond_false)
llvm::Value * codegenFunctionOper(const Analyzer::FunctionOper *, const CompilationOptions &)
Executor * executor_
void add_qualifier_to_execution_unit(RelAlgExecutionUnit &ra_exe_unit, const std::shared_ptr< Analyzer::Expr > &qual)
Definition: IRCodegen.cpp:174
std::unordered_map< int, llvm::Value * > scan_idx_to_hash_pos_
Definition: CgenState.h:280
bool needs_error_check_
Definition: CgenState.h:283
std::vector< llvm::Value * > codegenArrayExpr(const Analyzer::ArrayExpr *, const CompilationOptions &)
Definition: ArrayIR.cpp:88
ExecutorDeviceType device_type_
llvm::Value * codegenUMinus(const Analyzer::UOper *, const CompilationOptions &)
PlanState * plan_state_
std::shared_ptr< JoinHashTableInterface > hash_table
Definition: Execute.h:856
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:25
#define CHECK_LT(x, y)
Definition: Logger.h:197
#define IS_ARITHMETIC(X)
Definition: sqldefs.h:61
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value *> &args)
Definition: CgenState.cpp:134
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:333
llvm::Value * codegenFunctionOperWithCustomTypeHandling(const Analyzer::FunctionOperWithCustomTypeHandling *, const CompilationOptions &)
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:184
std::list< std::shared_ptr< Analyzer::Expr > > quals
const bool allow_loop_joins
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
llvm::Value * codegenUnnest(const Analyzer::UOper *, const CompilationOptions &)
Definition: ArrayIR.cpp:20
std::list< std::shared_ptr< Analyzer::Expr > > quals
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:503
#define CHECK(condition)
Definition: Logger.h:187
llvm::Value * codegenLogical(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:289
void check_if_loop_join_is_allowed(RelAlgExecutionUnit &ra_exe_unit, const ExecutionOptions &eo, const std::vector< InputTableInfo > &query_infos, const size_t level_idx, const std::string &fail_reason)
Definition: IRCodegen.cpp:184
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::unordered_map< int, std::unordered_map< int, std::shared_ptr< const ColumnarResults > > > ColumnCacheMap
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:20
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:157
std::vector< JoinLoop > buildJoinLoops(RelAlgExecutionUnit &ra_exe_unit, const CompilationOptions &co, const ExecutionOptions &eo, const std::vector< InputTableInfo > &query_infos, ColumnCacheMap &column_cache)
Definition: IRCodegen.cpp:206
std::function< llvm::Value *(const std::vector< llvm::Value * > &, llvm::Value *)> buildIsDeletedCb(const RelAlgExecutionUnit &ra_exe_unit, const size_t level_idx, const CompilationOptions &co)
Definition: IRCodegen.cpp:328
llvm::Value * addJoinLoopIterator(const std::vector< llvm::Value *> &prev_iters, const size_t level_idx)
Definition: IRCodegen.cpp:430
Definition: sqldefs.h:39
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:247
#define VLOG(n)
Definition: Logger.h:277
std::shared_ptr< JoinHashTableInterface > buildCurrentLevelHashTable(const JoinCondition &current_level_join_conditions, RelAlgExecutionUnit &ra_exe_unit, const CompilationOptions &co, const std::vector< InputTableInfo > &query_infos, ColumnCacheMap &column_cache, std::vector< std::string > &fail_reasons)
Definition: IRCodegen.cpp:384
std::list< std::shared_ptr< Analyzer::Expr > > simple_quals
SQLOps get_optype() const
Definition: Analyzer.h:363
#define IS_COMPARISON(X)
Definition: sqldefs.h:57