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