OmniSciDB  b24e664e58
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ArithmeticIR.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 "CodeGenerator.h"
18 #include "Execute.h"
19 
20 #include "Parser/ParserNode.h"
21 
22 // Code generation routines and helpers for basic arithmetic and unary minus.
23 
24 namespace {
25 
27  const SQLTypeInfo& ti2) {
28  if (ti2.is_timeinterval()) {
29  return numeric_type_name(ti2);
30  }
31  return numeric_type_name(ti1);
32 }
33 
34 } // namespace
35 
36 llvm::Value* CodeGenerator::codegenArith(const Analyzer::BinOper* bin_oper,
37  const CompilationOptions& co) {
38  const auto optype = bin_oper->get_optype();
39  CHECK(IS_ARITHMETIC(optype));
40  const auto lhs = bin_oper->get_left_operand();
41  const auto rhs = bin_oper->get_right_operand();
42  const auto& lhs_type = lhs->get_type_info();
43  const auto& rhs_type = rhs->get_type_info();
44 
45  if (lhs_type.is_decimal() && rhs_type.is_decimal() && optype == kDIVIDE) {
46  const auto ret = codegenDeciDiv(bin_oper, co);
47  if (ret) {
48  return ret;
49  }
50  }
51 
52  auto lhs_lv = codegen(lhs, true, co).front();
53  auto rhs_lv = codegen(rhs, true, co).front();
54  // Handle operations when a time interval operand is involved, an operation
55  // between an integer and a time interval isn't normalized by the analyzer.
56  if (lhs_type.is_timeinterval()) {
57  rhs_lv = codegenCastBetweenIntTypes(rhs_lv, rhs_type, lhs_type);
58  } else if (rhs_type.is_timeinterval()) {
59  lhs_lv = codegenCastBetweenIntTypes(lhs_lv, lhs_type, rhs_type);
60  } else {
61  CHECK_EQ(lhs_type.get_type(), rhs_type.get_type());
62  }
63  if (lhs_type.is_integer() || lhs_type.is_decimal() || lhs_type.is_timeinterval()) {
64  return codegenIntArith(bin_oper, lhs_lv, rhs_lv, co);
65  }
66  if (lhs_type.is_fp()) {
67  return codegenFpArith(bin_oper, lhs_lv, rhs_lv);
68  }
69  CHECK(false);
70  return nullptr;
71 }
72 
73 // Handle integer or integer-like (decimal, time, date) operand types.
75  llvm::Value* lhs_lv,
76  llvm::Value* rhs_lv,
77  const CompilationOptions& co) {
78  const auto lhs = bin_oper->get_left_operand();
79  const auto rhs = bin_oper->get_right_operand();
80  const auto& lhs_type = lhs->get_type_info();
81  const auto& rhs_type = rhs->get_type_info();
82  const auto int_typename = numeric_or_time_interval_type_name(lhs_type, rhs_type);
83  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
84  const auto& oper_type = rhs_type.is_timeinterval() ? rhs_type : lhs_type;
85  switch (bin_oper->get_optype()) {
86  case kMINUS:
87  return codegenSub(bin_oper,
88  lhs_lv,
89  rhs_lv,
90  null_check_suffix.empty() ? "" : int_typename,
91  null_check_suffix,
92  oper_type,
93  co);
94  case kPLUS:
95  return codegenAdd(bin_oper,
96  lhs_lv,
97  rhs_lv,
98  null_check_suffix.empty() ? "" : int_typename,
99  null_check_suffix,
100  oper_type,
101  co);
102  case kMULTIPLY:
103  return codegenMul(bin_oper,
104  lhs_lv,
105  rhs_lv,
106  null_check_suffix.empty() ? "" : int_typename,
107  null_check_suffix,
108  oper_type,
109  co);
110  case kDIVIDE:
111  return codegenDiv(lhs_lv,
112  rhs_lv,
113  null_check_suffix.empty() ? "" : int_typename,
114  null_check_suffix,
115  oper_type);
116  case kMODULO:
117  return codegenMod(lhs_lv,
118  rhs_lv,
119  null_check_suffix.empty() ? "" : int_typename,
120  null_check_suffix,
121  oper_type);
122  default:
123  CHECK(false);
124  }
125  CHECK(false);
126  return nullptr;
127 }
128 
129 // Handle floating point operand types.
131  llvm::Value* lhs_lv,
132  llvm::Value* rhs_lv) {
133  const auto lhs = bin_oper->get_left_operand();
134  const auto rhs = bin_oper->get_right_operand();
135  const auto& lhs_type = lhs->get_type_info();
136  const auto& rhs_type = rhs->get_type_info();
137  const auto fp_typename = numeric_type_name(lhs_type);
138  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
139  llvm::ConstantFP* fp_null{lhs_type.get_type() == kFLOAT
142  switch (bin_oper->get_optype()) {
143  case kMINUS:
144  return null_check_suffix.empty()
145  ? cgen_state_->ir_builder_.CreateFSub(lhs_lv, rhs_lv)
146  : cgen_state_->emitCall("sub_" + fp_typename + null_check_suffix,
147  {lhs_lv, rhs_lv, fp_null});
148  case kPLUS:
149  return null_check_suffix.empty()
150  ? cgen_state_->ir_builder_.CreateFAdd(lhs_lv, rhs_lv)
151  : cgen_state_->emitCall("add_" + fp_typename + null_check_suffix,
152  {lhs_lv, rhs_lv, fp_null});
153  case kMULTIPLY:
154  return null_check_suffix.empty()
155  ? cgen_state_->ir_builder_.CreateFMul(lhs_lv, rhs_lv)
156  : cgen_state_->emitCall("mul_" + fp_typename + null_check_suffix,
157  {lhs_lv, rhs_lv, fp_null});
158  case kDIVIDE:
159  return codegenDiv(lhs_lv,
160  rhs_lv,
161  null_check_suffix.empty() ? "" : fp_typename,
162  null_check_suffix,
163  lhs_type);
164  default:
165  CHECK(false);
166  }
167  CHECK(false);
168  return nullptr;
169 }
170 
171 namespace {
172 
174  const auto col_expr = dynamic_cast<const Analyzer::ColumnVar*>(expr);
175  if (!col_expr) {
176  return false;
177  }
178  return col_expr->get_table_id() < 0;
179 }
180 
181 } // namespace
182 
183 // Returns true iff runtime overflow checks aren't needed thanks to range information.
185  int64_t min,
186  int64_t max) {
187  if (is_temporary_column(bin_oper->get_left_operand()) ||
188  is_temporary_column(bin_oper->get_right_operand())) {
189  // Computing the range for temporary columns is a lot more expensive than the overflow
190  // check.
191  return false;
192  }
193  if (bin_oper->get_type_info().is_decimal()) {
194  return false;
195  }
196 
197  auto expr_range_info =
198  cgen_state_->query_infos_.size() > 0
201  if (expr_range_info.getType() != ExpressionRangeType::Integer) {
202  return false;
203  }
204  if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
205  return true;
206  }
207 
208  return false;
209 }
210 
211 llvm::Value* CodeGenerator::codegenAdd(const Analyzer::BinOper* bin_oper,
212  llvm::Value* lhs_lv,
213  llvm::Value* rhs_lv,
214  const std::string& null_typename,
215  const std::string& null_check_suffix,
216  const SQLTypeInfo& ti,
217  const CompilationOptions& co) {
218  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
219  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
220  llvm::Value* chosen_max{nullptr};
221  llvm::Value* chosen_min{nullptr};
222  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
223  auto need_overflow_check =
224  !checkExpressionRanges(bin_oper,
225  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
226  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
227 
228  if (need_overflow_check && co.device_type_ == ExecutorDeviceType::CPU) {
230  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
231  }
232 
233  llvm::BasicBlock* add_ok{nullptr};
234  llvm::BasicBlock* add_fail{nullptr};
235  if (need_overflow_check) {
237  add_ok =
238  llvm::BasicBlock::Create(cgen_state_->context_, "add_ok", cgen_state_->row_func_);
239  if (!null_check_suffix.empty()) {
240  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, add_ok, ti);
241  }
242  add_fail = llvm::BasicBlock::Create(
243  cgen_state_->context_, "add_fail", cgen_state_->row_func_);
244  llvm::Value* detected{nullptr};
245  auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0, true);
246  auto overflow = cgen_state_->ir_builder_.CreateAnd(
247  cgen_state_->ir_builder_.CreateICmpSGT(lhs_lv, const_zero),
248  cgen_state_->ir_builder_.CreateICmpSGT(
249  rhs_lv, cgen_state_->ir_builder_.CreateSub(chosen_max, lhs_lv)));
250  auto underflow = cgen_state_->ir_builder_.CreateAnd(
251  cgen_state_->ir_builder_.CreateICmpSLT(lhs_lv, const_zero),
252  cgen_state_->ir_builder_.CreateICmpSLT(
253  rhs_lv, cgen_state_->ir_builder_.CreateSub(chosen_min, lhs_lv)));
254  detected = cgen_state_->ir_builder_.CreateOr(overflow, underflow);
255  cgen_state_->ir_builder_.CreateCondBr(detected, add_fail, add_ok);
256  cgen_state_->ir_builder_.SetInsertPoint(add_ok);
257  }
258  auto ret = null_check_suffix.empty()
259  ? cgen_state_->ir_builder_.CreateAdd(lhs_lv, rhs_lv)
261  "add_" + null_typename + null_check_suffix,
262  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
263  if (need_overflow_check) {
264  cgen_state_->ir_builder_.SetInsertPoint(add_fail);
265  cgen_state_->ir_builder_.CreateRet(
267  cgen_state_->ir_builder_.SetInsertPoint(add_ok);
268  }
269  return ret;
270 }
271 
272 llvm::Value* CodeGenerator::codegenSub(const Analyzer::BinOper* bin_oper,
273  llvm::Value* lhs_lv,
274  llvm::Value* rhs_lv,
275  const std::string& null_typename,
276  const std::string& null_check_suffix,
277  const SQLTypeInfo& ti,
278  const CompilationOptions& co) {
279  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
280  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
281  llvm::Value* chosen_max{nullptr};
282  llvm::Value* chosen_min{nullptr};
283  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
284  auto need_overflow_check =
285  !checkExpressionRanges(bin_oper,
286  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
287  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
288 
289  if (need_overflow_check && co.device_type_ == ExecutorDeviceType::CPU) {
291  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
292  }
293 
294  llvm::BasicBlock* sub_ok{nullptr};
295  llvm::BasicBlock* sub_fail{nullptr};
296  if (need_overflow_check) {
298  sub_ok =
299  llvm::BasicBlock::Create(cgen_state_->context_, "sub_ok", cgen_state_->row_func_);
300  if (!null_check_suffix.empty()) {
301  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, sub_ok, ti);
302  }
303  sub_fail = llvm::BasicBlock::Create(
304  cgen_state_->context_, "sub_fail", cgen_state_->row_func_);
305  llvm::Value* detected{nullptr};
306  auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0, true);
307  auto overflow = cgen_state_->ir_builder_.CreateAnd(
308  cgen_state_->ir_builder_.CreateICmpSLT(
309  rhs_lv, const_zero), // sub going up, check the max
310  cgen_state_->ir_builder_.CreateICmpSGT(
311  lhs_lv, cgen_state_->ir_builder_.CreateAdd(chosen_max, rhs_lv)));
312  auto underflow = cgen_state_->ir_builder_.CreateAnd(
313  cgen_state_->ir_builder_.CreateICmpSGT(
314  rhs_lv, const_zero), // sub going down, check the min
315  cgen_state_->ir_builder_.CreateICmpSLT(
316  lhs_lv, cgen_state_->ir_builder_.CreateAdd(chosen_min, rhs_lv)));
317  detected = cgen_state_->ir_builder_.CreateOr(overflow, underflow);
318  cgen_state_->ir_builder_.CreateCondBr(detected, sub_fail, sub_ok);
319  cgen_state_->ir_builder_.SetInsertPoint(sub_ok);
320  }
321  auto ret = null_check_suffix.empty()
322  ? cgen_state_->ir_builder_.CreateSub(lhs_lv, rhs_lv)
324  "sub_" + null_typename + null_check_suffix,
325  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
326  if (need_overflow_check) {
327  cgen_state_->ir_builder_.SetInsertPoint(sub_fail);
328  cgen_state_->ir_builder_.CreateRet(
330  cgen_state_->ir_builder_.SetInsertPoint(sub_ok);
331  }
332  return ret;
333 }
334 
336  llvm::Value* rhs_lv,
337  llvm::BasicBlock* no_overflow_bb,
338  const SQLTypeInfo& ti) {
339  const auto lhs_is_null_lv = codegenIsNullNumber(lhs_lv, ti);
340  const auto has_null_operand_lv =
341  rhs_lv ? cgen_state_->ir_builder_.CreateOr(lhs_is_null_lv,
342  codegenIsNullNumber(rhs_lv, ti))
343  : lhs_is_null_lv;
344  auto operands_not_null = llvm::BasicBlock::Create(
345  cgen_state_->context_, "operands_not_null", cgen_state_->row_func_);
346  cgen_state_->ir_builder_.CreateCondBr(
347  has_null_operand_lv, no_overflow_bb, operands_not_null);
348  cgen_state_->ir_builder_.SetInsertPoint(operands_not_null);
349 }
350 
351 llvm::Value* CodeGenerator::codegenMul(const Analyzer::BinOper* bin_oper,
352  llvm::Value* lhs_lv,
353  llvm::Value* rhs_lv,
354  const std::string& null_typename,
355  const std::string& null_check_suffix,
356  const SQLTypeInfo& ti,
357  const CompilationOptions& co,
358  bool downscale) {
359  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
360  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
361  llvm::Value* chosen_max{nullptr};
362  llvm::Value* chosen_min{nullptr};
363  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
364  auto need_overflow_check =
365  !checkExpressionRanges(bin_oper,
366  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
367  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
368 
369  if (need_overflow_check && co.device_type_ == ExecutorDeviceType::CPU) {
371  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
372  }
373 
374  llvm::BasicBlock* mul_ok{nullptr};
375  llvm::BasicBlock* mul_fail{nullptr};
376  if (need_overflow_check) {
378  mul_ok =
379  llvm::BasicBlock::Create(cgen_state_->context_, "mul_ok", cgen_state_->row_func_);
380  if (!null_check_suffix.empty()) {
381  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, mul_ok, ti);
382  }
383  mul_fail = llvm::BasicBlock::Create(
384  cgen_state_->context_, "mul_fail", cgen_state_->row_func_);
385  auto mul_check = llvm::BasicBlock::Create(
386  cgen_state_->context_, "mul_check", cgen_state_->row_func_);
387  auto const_zero = llvm::ConstantInt::get(rhs_lv->getType(), 0, true);
388  cgen_state_->ir_builder_.CreateCondBr(
389  cgen_state_->ir_builder_.CreateICmpEQ(rhs_lv, const_zero), mul_ok, mul_check);
390  cgen_state_->ir_builder_.SetInsertPoint(mul_check);
391  auto rhs_is_negative_lv = cgen_state_->ir_builder_.CreateICmpSLT(rhs_lv, const_zero);
392  auto positive_rhs_lv = cgen_state_->ir_builder_.CreateSelect(
393  rhs_is_negative_lv, cgen_state_->ir_builder_.CreateNeg(rhs_lv), rhs_lv);
394  auto adjusted_lhs_lv = cgen_state_->ir_builder_.CreateSelect(
395  rhs_is_negative_lv, cgen_state_->ir_builder_.CreateNeg(lhs_lv), lhs_lv);
396  auto detected = cgen_state_->ir_builder_.CreateOr( // overflow
397  cgen_state_->ir_builder_.CreateICmpSGT(
398  adjusted_lhs_lv,
399  cgen_state_->ir_builder_.CreateSDiv(chosen_max, positive_rhs_lv)),
400  // underflow
401  cgen_state_->ir_builder_.CreateICmpSLT(
402  adjusted_lhs_lv,
403  cgen_state_->ir_builder_.CreateSDiv(chosen_min, positive_rhs_lv)));
404  cgen_state_->ir_builder_.CreateCondBr(detected, mul_fail, mul_ok);
405  cgen_state_->ir_builder_.SetInsertPoint(mul_ok);
406  }
407  const auto ret =
408  null_check_suffix.empty()
409  ? cgen_state_->ir_builder_.CreateMul(lhs_lv, rhs_lv)
411  "mul_" + null_typename + null_check_suffix,
412  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
413  if (need_overflow_check) {
414  cgen_state_->ir_builder_.SetInsertPoint(mul_fail);
415  cgen_state_->ir_builder_.CreateRet(
417  cgen_state_->ir_builder_.SetInsertPoint(mul_ok);
418  }
419  return ret;
420 }
421 
422 llvm::Value* CodeGenerator::codegenDiv(llvm::Value* lhs_lv,
423  llvm::Value* rhs_lv,
424  const std::string& null_typename,
425  const std::string& null_check_suffix,
426  const SQLTypeInfo& ti,
427  bool upscale) {
428  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
429  if (ti.is_decimal()) {
430  if (upscale) {
431  CHECK(lhs_lv->getType()->isIntegerTy());
432  const auto scale_lv =
433  llvm::ConstantInt::get(lhs_lv->getType(), exp_to_scale(ti.get_scale()));
434 
435  lhs_lv = cgen_state_->ir_builder_.CreateSExt(
436  lhs_lv, get_int_type(64, cgen_state_->context_));
437  llvm::Value* chosen_max{nullptr};
438  llvm::Value* chosen_min{nullptr};
439  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(8, true);
440  auto decimal_div_ok = llvm::BasicBlock::Create(
441  cgen_state_->context_, "decimal_div_ok", cgen_state_->row_func_);
442  if (!null_check_suffix.empty()) {
443  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, decimal_div_ok, ti);
444  }
445  auto decimal_div_fail = llvm::BasicBlock::Create(
446  cgen_state_->context_, "decimal_div_fail", cgen_state_->row_func_);
447  auto lhs_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() /
448  exp_to_scale(ti.get_scale());
449  auto lhs_max_lv =
450  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), lhs_max);
451  llvm::Value* detected{nullptr};
452  if (ti.get_notnull()) {
453  detected = cgen_state_->ir_builder_.CreateICmpSGT(lhs_lv, lhs_max_lv);
454  } else {
455  detected = toBool(cgen_state_->emitCall(
456  "gt_" + numeric_type_name(ti) + "_nullable",
457  {lhs_lv,
458  lhs_max_lv,
461  }
462  cgen_state_->ir_builder_.CreateCondBr(detected, decimal_div_fail, decimal_div_ok);
463 
464  cgen_state_->ir_builder_.SetInsertPoint(decimal_div_fail);
465  cgen_state_->ir_builder_.CreateRet(
467 
468  cgen_state_->ir_builder_.SetInsertPoint(decimal_div_ok);
469 
470  lhs_lv = null_typename.empty()
471  ? cgen_state_->ir_builder_.CreateMul(lhs_lv, scale_lv)
473  "mul_" + numeric_type_name(ti) + null_check_suffix,
474  {lhs_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(ti))});
475  }
476  }
477  if (g_null_div_by_zero) {
478  llvm::Value* null_lv{nullptr};
479  if (ti.is_fp()) {
480  null_lv = ti.get_type() == kFLOAT ? cgen_state_->llFp(NULL_FLOAT)
482  } else {
483  null_lv = cgen_state_->llInt(inline_int_null_val(ti));
484  }
485  return cgen_state_->emitCall("safe_div_" + numeric_type_name(ti),
486  {lhs_lv, rhs_lv, null_lv});
487  }
489  auto div_ok =
490  llvm::BasicBlock::Create(cgen_state_->context_, "div_ok", cgen_state_->row_func_);
491  if (!null_check_suffix.empty()) {
492  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, div_ok, ti);
493  }
494  auto div_zero =
495  llvm::BasicBlock::Create(cgen_state_->context_, "div_zero", cgen_state_->row_func_);
496  auto zero_const = rhs_lv->getType()->isIntegerTy()
497  ? llvm::ConstantInt::get(rhs_lv->getType(), 0, true)
498  : llvm::ConstantFP::get(rhs_lv->getType(), 0.);
499  cgen_state_->ir_builder_.CreateCondBr(
500  zero_const->getType()->isFloatingPointTy()
501  ? cgen_state_->ir_builder_.CreateFCmp(
502  llvm::FCmpInst::FCMP_ONE, rhs_lv, zero_const)
503  : cgen_state_->ir_builder_.CreateICmp(
504  llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
505  div_ok,
506  div_zero);
507  cgen_state_->ir_builder_.SetInsertPoint(div_ok);
508  auto ret =
509  zero_const->getType()->isIntegerTy()
510  ? (null_typename.empty()
511  ? cgen_state_->ir_builder_.CreateSDiv(lhs_lv, rhs_lv)
513  "div_" + null_typename + null_check_suffix,
514  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))}))
515  : (null_typename.empty()
516  ? cgen_state_->ir_builder_.CreateFDiv(lhs_lv, rhs_lv)
518  "div_" + null_typename + null_check_suffix,
519  {lhs_lv,
520  rhs_lv,
523  cgen_state_->ir_builder_.SetInsertPoint(div_zero);
525  cgen_state_->ir_builder_.SetInsertPoint(div_ok);
526  return ret;
527 }
528 
529 // Handle decimal division by an integer (constant or cast), return null if
530 // the expression doesn't match this pattern and let the general method kick in.
531 // For said patterns, we can simply divide the decimal operand by the non-scaled
532 // integer value instead of using the scaled value preceded by a multiplication.
533 // It is both more efficient and avoids the overflow for a lot of practical cases.
535  const CompilationOptions& co) {
536  auto lhs = bin_oper->get_left_operand();
537  auto rhs = bin_oper->get_right_operand();
538  const auto& lhs_type = lhs->get_type_info();
539  const auto& rhs_type = rhs->get_type_info();
540  CHECK(lhs_type.is_decimal() && rhs_type.is_decimal() &&
541  lhs_type.get_scale() == rhs_type.get_scale());
542 
543  auto rhs_constant = dynamic_cast<const Analyzer::Constant*>(rhs);
544  auto rhs_cast = dynamic_cast<const Analyzer::UOper*>(rhs);
545  if (rhs_constant && !rhs_constant->get_is_null() &&
546  rhs_constant->get_constval().bigintval != 0LL &&
547  (rhs_constant->get_constval().bigintval % exp_to_scale(rhs_type.get_scale())) ==
548  0LL) {
549  // can safely downscale a scaled constant
550  } else if (rhs_cast && rhs_cast->get_optype() == kCAST &&
551  rhs_cast->get_operand()->get_type_info().is_integer()) {
552  // can skip upscale in the int to dec cast
553  } else {
554  return nullptr;
555  }
556 
557  auto lhs_lv = codegen(lhs, true, co).front();
558  llvm::Value* rhs_lv{nullptr};
559  if (rhs_constant) {
560  const auto rhs_lit = Parser::IntLiteral::analyzeValue(
561  rhs_constant->get_constval().bigintval / exp_to_scale(rhs_type.get_scale()));
562  auto rhs_lit_lv =
563  codegenIntConst(dynamic_cast<const Analyzer::Constant*>(rhs_lit.get()));
565  rhs_lit_lv, rhs_lit->get_type_info(), lhs_type, /*upscale*/ false);
566  } else if (rhs_cast) {
567  auto rhs_cast_oper = rhs_cast->get_operand();
568  const auto& rhs_cast_oper_ti = rhs_cast_oper->get_type_info();
569  auto rhs_cast_oper_lv = codegen(rhs_cast_oper, true, co).front();
571  rhs_cast_oper_lv, rhs_cast_oper_ti, lhs_type, /*upscale*/ false);
572  } else {
573  CHECK(false);
574  }
575  const auto int_typename = numeric_or_time_interval_type_name(lhs_type, rhs_type);
576  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
577  return codegenDiv(lhs_lv,
578  rhs_lv,
579  null_check_suffix.empty() ? "" : int_typename,
580  null_check_suffix,
581  lhs_type,
582  /*upscale*/ false);
583 }
584 
585 llvm::Value* CodeGenerator::codegenMod(llvm::Value* lhs_lv,
586  llvm::Value* rhs_lv,
587  const std::string& null_typename,
588  const std::string& null_check_suffix,
589  const SQLTypeInfo& ti) {
590  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
591  CHECK(ti.is_integer());
593  // Generate control flow for division by zero error handling.
594  auto mod_ok =
595  llvm::BasicBlock::Create(cgen_state_->context_, "mod_ok", cgen_state_->row_func_);
596  auto mod_zero =
597  llvm::BasicBlock::Create(cgen_state_->context_, "mod_zero", cgen_state_->row_func_);
598  auto zero_const = llvm::ConstantInt::get(rhs_lv->getType(), 0, true);
599  cgen_state_->ir_builder_.CreateCondBr(
600  cgen_state_->ir_builder_.CreateICmp(llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
601  mod_ok,
602  mod_zero);
603  cgen_state_->ir_builder_.SetInsertPoint(mod_ok);
604  auto ret = null_typename.empty()
605  ? cgen_state_->ir_builder_.CreateSRem(lhs_lv, rhs_lv)
607  "mod_" + null_typename + null_check_suffix,
608  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
609  cgen_state_->ir_builder_.SetInsertPoint(mod_zero);
611  cgen_state_->ir_builder_.SetInsertPoint(mod_ok);
612  return ret;
613 }
614 
615 // Returns true iff runtime overflow checks aren't needed thanks to range information.
617  int64_t min,
618  int64_t max) {
619  if (uoper->get_type_info().is_decimal()) {
620  return false;
621  }
622 
623  auto expr_range_info =
624  cgen_state_->query_infos_.size() > 0
627  if (expr_range_info.getType() != ExpressionRangeType::Integer) {
628  return false;
629  }
630  if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
631  return true;
632  }
633 
634  return false;
635 }
636 
638  const CompilationOptions& co) {
639  CHECK_EQ(uoper->get_optype(), kUMINUS);
640  const auto operand_lv = codegen(uoper->get_operand(), true, co).front();
641  const auto& ti = uoper->get_type_info();
642  llvm::Value* chosen_max{nullptr};
643  llvm::Value* chosen_min{nullptr};
644  bool need_overflow_check = false;
645  if (ti.is_integer() || ti.is_decimal() || ti.is_timeinterval()) {
646  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
647  need_overflow_check = !checkExpressionRanges(
648  uoper,
649  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
650  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
651  }
652  llvm::BasicBlock* uminus_ok{nullptr};
653  llvm::BasicBlock* uminus_fail{nullptr};
654  if (need_overflow_check) {
656  uminus_ok = llvm::BasicBlock::Create(
657  cgen_state_->context_, "uminus_ok", cgen_state_->row_func_);
658  if (!ti.get_notnull()) {
659  codegenSkipOverflowCheckForNull(operand_lv, nullptr, uminus_ok, ti);
660  }
661  uminus_fail = llvm::BasicBlock::Create(
662  cgen_state_->context_, "uminus_fail", cgen_state_->row_func_);
663  auto const_min = llvm::ConstantInt::get(
664  operand_lv->getType(),
665  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
666  true);
667  auto overflow = cgen_state_->ir_builder_.CreateICmpEQ(operand_lv, const_min);
668  cgen_state_->ir_builder_.CreateCondBr(overflow, uminus_fail, uminus_ok);
669  cgen_state_->ir_builder_.SetInsertPoint(uminus_ok);
670  }
671  auto ret =
672  ti.get_notnull()
673  ? (ti.is_fp() ? cgen_state_->ir_builder_.CreateFNeg(operand_lv)
674  : cgen_state_->ir_builder_.CreateNeg(operand_lv))
676  "uminus_" + numeric_type_name(ti) + "_nullable",
677  {operand_lv,
678  ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(ti))
679  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(ti))});
680  if (need_overflow_check) {
681  cgen_state_->ir_builder_.SetInsertPoint(uminus_fail);
682  cgen_state_->ir_builder_.CreateRet(
684  cgen_state_->ir_builder_.SetInsertPoint(uminus_ok);
685  }
686  return ret;
687 }
688 
690  const Analyzer::BinOper* bin_oper,
691  llvm::Type* type) {
692  llvm::Intrinsic::ID fn_id{llvm::Intrinsic::not_intrinsic};
693  switch (bin_oper->get_optype()) {
694  case kMINUS:
695  fn_id = llvm::Intrinsic::ssub_with_overflow;
696  break;
697  case kPLUS:
698  fn_id = llvm::Intrinsic::sadd_with_overflow;
699  break;
700  case kMULTIPLY:
701  fn_id = llvm::Intrinsic::smul_with_overflow;
702  break;
703  default:
704  LOG(FATAL) << "unexpected arith with overflow optype: " << bin_oper->toString();
705  }
706 
707  return llvm::Intrinsic::getDeclaration(cgen_state_->module_, fn_id, type);
708 }
709 
711  const Analyzer::BinOper* bin_oper,
712  llvm::Value* lhs_lv,
713  llvm::Value* rhs_lv,
714  const std::string& null_check_suffix,
715  const SQLTypeInfo& ti) {
717 
718  llvm::BasicBlock* check_ok =
719  llvm::BasicBlock::Create(cgen_state_->context_, "ovf_ok", cgen_state_->row_func_);
720  llvm::BasicBlock* check_fail = llvm::BasicBlock::Create(
721  cgen_state_->context_, "ovf_detected", cgen_state_->row_func_);
722  llvm::BasicBlock* null_check{nullptr};
723 
724  if (!null_check_suffix.empty()) {
725  null_check = cgen_state_->ir_builder_.GetInsertBlock();
726  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, check_ok, ti);
727  }
728 
729  // Compute result and overflow flag
730  auto func = getArithWithOverflowIntrinsic(bin_oper, lhs_lv->getType());
731  auto ret_and_overflow = cgen_state_->ir_builder_.CreateCall(
732  func, std::vector<llvm::Value*>{lhs_lv, rhs_lv});
733  auto ret = cgen_state_->ir_builder_.CreateExtractValue(ret_and_overflow,
734  std::vector<unsigned>{0});
735  auto overflow = cgen_state_->ir_builder_.CreateExtractValue(ret_and_overflow,
736  std::vector<unsigned>{1});
737  auto val_bb = cgen_state_->ir_builder_.GetInsertBlock();
738 
739  // Return error on overflow
740  cgen_state_->ir_builder_.CreateCondBr(overflow, check_fail, check_ok);
741  cgen_state_->ir_builder_.SetInsertPoint(check_fail);
742  cgen_state_->ir_builder_.CreateRet(
744 
745  cgen_state_->ir_builder_.SetInsertPoint(check_ok);
746 
747  // In case of null check we have to use NULL result on check fail
748  if (null_check) {
749  auto phi = cgen_state_->ir_builder_.CreatePHI(ret->getType(), 2);
750  phi->addIncoming(llvm::ConstantInt::get(ret->getType(), inline_int_null_val(ti)),
751  null_check);
752  phi->addIncoming(ret, val_bb);
753  ret = phi;
754  }
755 
756  return ret;
757 }
int get_table_id() const
Definition: Analyzer.h:194
bool is_fp() const
Definition: sqltypes.h:481
llvm::Value * codegenIntArith(const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const CompilationOptions &)
#define CHECK_EQ(x, y)
Definition: Logger.h:198
#define NULL_DOUBLE
Definition: sqltypes.h:179
llvm::Value * codegenArith(const Analyzer::BinOper *, const CompilationOptions &)
const std::vector< InputTableInfo > & query_infos_
Definition: CgenState.h:283
CgenState * cgen_state_
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:112
#define LOG(tag)
Definition: Logger.h:185
const Expr * get_right_operand() const
Definition: Analyzer.h:437
llvm::Value * codegenMod(llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:269
HOST DEVICE int get_scale() const
Definition: sqltypes.h:331
HOST DEVICE int get_size() const
Definition: sqltypes.h:336
Definition: sqldefs.h:49
Definition: sqldefs.h:41
llvm::Value * codegenDeciDiv(const Analyzer::BinOper *, const CompilationOptions &)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string toString() const override
Definition: Analyzer.cpp:2349
llvm::Function * row_func_
Definition: CgenState.h:265
llvm::Value * codegenFpArith(const Analyzer::BinOper *, llvm::Value *, llvm::Value *)
bool g_null_div_by_zero
Definition: Execute.cpp:75
SQLOps get_optype() const
Definition: Analyzer.h:433
llvm::Module * module_
Definition: CgenState.h:264
static const int32_t ERR_DIV_BY_ZERO
Definition: Execute.h:1033
llvm::LLVMContext & context_
Definition: CgenState.h:267
llvm::Value * codegenDiv(llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &, bool upscale=true)
std::string numeric_or_time_interval_type_name(const SQLTypeInfo &ti1, const SQLTypeInfo &ti2)
CHECK(cgen_state)
Classes representing a parse tree.
bool is_temporary_column(const Analyzer::Expr *expr)
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:326
void codegenSkipOverflowCheckForNull(llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:24
#define NULL_FLOAT
Definition: sqltypes.h:178
llvm::Value * codegenBinOpWithOverflowForCPU(const Analyzer::BinOper *bin_oper, llvm::Value *lhs_lv, llvm::Value *rhs_lv, const std::string &null_check_suffix, const SQLTypeInfo &ti)
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1039
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:228
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:333
bool needs_error_check_
Definition: CgenState.h:284
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:252
ExpressionRange getExpressionRange(const Analyzer::BinOper *expr, const std::vector< InputTableInfo > &query_infos, const Executor *, boost::optional< std::list< std::shared_ptr< Analyzer::Expr >>> simple_quals)
llvm::Function * getArithWithOverflowIntrinsic(const Analyzer::BinOper *bin_oper, llvm::Type *type)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1074
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:852
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
ExecutorDeviceType device_type_
llvm::Value * codegenUMinus(const Analyzer::UOper *, const CompilationOptions &)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:134
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:25
Definition: sqldefs.h:40
#define IS_ARITHMETIC(X)
Definition: sqldefs.h:61
const Expr * get_operand() const
Definition: Analyzer.h:365
bool is_integer() const
Definition: sqltypes.h:479
llvm::Value * codegenSub(const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &, const CompilationOptions &)
bool is_timeinterval() const
Definition: sqltypes.h:488
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:333
llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant)
Definition: ConstantIR.cpp:88
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:248
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
Definition: LogicalIR.cpp:397
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
const Expr * get_left_operand() const
Definition: Analyzer.h:436
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:160
static ExpressionRange makeInvalidRange()
llvm::Value * codegenMul(const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &, const CompilationOptions &, bool downscale=true)
bool is_decimal() const
Definition: sqltypes.h:480
llvm::Value * codegenAdd(const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &, const CompilationOptions &)
bool checkExpressionRanges(const Analyzer::UOper *, int64_t, int64_t)
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:74
SQLOps get_optype() const
Definition: Analyzer.h:364
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:62
Executor * executor() const