44 const auto& rhs_type = rhs->get_type_info();
46 if (lhs_type.is_decimal() && rhs_type.is_decimal() && optype ==
kDIVIDE) {
53 auto lhs_lv =
codegen(lhs,
true, co).front();
54 auto rhs_lv =
codegen(rhs,
true, co).front();
57 if (lhs_type.is_timeinterval()) {
59 }
else if (rhs_type.is_timeinterval()) {
62 CHECK_EQ(lhs_type.get_type(), rhs_type.get_type());
64 if (lhs_type.is_integer() || lhs_type.is_decimal() || lhs_type.is_timeinterval()) {
67 if (lhs_type.is_fp()) {
83 const auto& rhs_type = rhs->get_type_info();
86 const auto& oper_type = rhs_type.is_timeinterval() ? rhs_type : lhs_type;
92 null_check_suffix.empty() ?
"" : int_typename,
100 null_check_suffix.empty() ?
"" : int_typename,
108 null_check_suffix.empty() ?
"" : int_typename,
115 null_check_suffix.empty() ?
"" : int_typename,
121 null_check_suffix.empty() ?
"" : int_typename,
134 llvm::Value* rhs_lv) {
139 const auto& rhs_type = rhs->get_type_info();
142 llvm::ConstantFP* fp_null{lhs_type.get_type() ==
kFLOAT
147 return null_check_suffix.empty()
150 {lhs_lv, rhs_lv, fp_null});
152 return null_check_suffix.empty()
155 {lhs_lv, rhs_lv, fp_null});
157 return null_check_suffix.empty()
160 {lhs_lv, rhs_lv, fp_null});
164 null_check_suffix.empty() ?
"" : fp_typename,
202 auto expr_range_info =
209 if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
220 const std::string& null_typename,
221 const std::string& null_check_suffix,
225 CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
227 llvm::Value* chosen_max{
nullptr};
228 llvm::Value* chosen_min{
nullptr};
230 auto need_overflow_check =
232 static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
233 static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
237 bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
240 llvm::BasicBlock* add_ok{
nullptr};
241 llvm::BasicBlock* add_fail{
nullptr};
242 if (need_overflow_check) {
244 add_ok = llvm::BasicBlock::Create(
246 if (!null_check_suffix.empty()) {
249 add_fail = llvm::BasicBlock::Create(
251 llvm::Value* detected{
nullptr};
252 auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0,
true);
265 auto ret = null_check_suffix.empty()
268 "add_" + null_typename + null_check_suffix,
270 if (need_overflow_check) {
282 const std::string& null_typename,
283 const std::string& null_check_suffix,
287 CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
289 llvm::Value* chosen_max{
nullptr};
290 llvm::Value* chosen_min{
nullptr};
292 auto need_overflow_check =
294 static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
295 static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
299 bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
302 llvm::BasicBlock* sub_ok{
nullptr};
303 llvm::BasicBlock* sub_fail{
nullptr};
304 if (need_overflow_check) {
306 sub_ok = llvm::BasicBlock::Create(
308 if (!null_check_suffix.empty()) {
311 sub_fail = llvm::BasicBlock::Create(
313 llvm::Value* detected{
nullptr};
314 auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0,
true);
329 auto ret = null_check_suffix.empty()
332 "sub_" + null_typename + null_check_suffix,
334 if (need_overflow_check) {
345 llvm::BasicBlock* no_overflow_bb,
348 const auto has_null_operand_lv =
352 auto operands_not_null = llvm::BasicBlock::Create(
355 has_null_operand_lv, no_overflow_bb, operands_not_null);
362 const std::string& null_typename,
363 const std::string& null_check_suffix,
368 CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
370 llvm::Value* chosen_max{
nullptr};
371 llvm::Value* chosen_min{
nullptr};
373 auto need_overflow_check =
375 static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
376 static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
380 bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
383 llvm::BasicBlock* mul_ok{
nullptr};
384 llvm::BasicBlock* mul_fail{
nullptr};
385 if (need_overflow_check) {
387 mul_ok = llvm::BasicBlock::Create(
389 if (!null_check_suffix.empty()) {
392 mul_fail = llvm::BasicBlock::Create(
394 auto mul_check = llvm::BasicBlock::Create(
396 auto const_zero = llvm::ConstantInt::get(rhs_lv->getType(), 0,
true);
417 null_check_suffix.empty()
420 "mul_" + null_typename + null_check_suffix,
422 if (need_overflow_check) {
433 const std::string& null_typename,
434 const std::string& null_check_suffix,
438 CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
441 CHECK(lhs_lv->getType()->isIntegerTy());
442 const auto scale_lv =
447 llvm::Value* chosen_max{
nullptr};
448 llvm::Value* chosen_min{
nullptr};
450 auto decimal_div_ok = llvm::BasicBlock::Create(
452 if (!null_check_suffix.empty()) {
455 auto decimal_div_fail = llvm::BasicBlock::Create(
457 auto lhs_max =
static_cast<llvm::ConstantInt*
>(chosen_max)->getSExtValue() /
461 llvm::Value* detected{
nullptr};
480 lhs_lv = null_typename.empty()
488 llvm::Value* null_lv{
nullptr};
496 {lhs_lv, rhs_lv, null_lv});
499 auto div_ok = llvm::BasicBlock::Create(
501 if (!null_check_suffix.empty()) {
504 auto div_zero = llvm::BasicBlock::Create(
506 auto zero_const = rhs_lv->getType()->isIntegerTy()
507 ? llvm::ConstantInt::get(rhs_lv->getType(), 0,
true)
508 : llvm::ConstantFP::get(rhs_lv->getType(), 0.);
510 zero_const->getType()->isFloatingPointTy()
512 llvm::FCmpInst::FCMP_ONE, rhs_lv, zero_const)
514 llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
519 zero_const->getType()->isIntegerTy()
520 ? (null_typename.empty()
523 "div_" + null_typename + null_check_suffix,
525 : (null_typename.empty()
528 "div_" + null_typename + null_check_suffix,
550 const auto& rhs_type = rhs->get_type_info();
551 CHECK(lhs_type.is_decimal() && rhs_type.is_decimal() &&
552 lhs_type.get_scale() == rhs_type.get_scale());
556 if (rhs_constant && !rhs_constant->get_is_null() &&
557 rhs_constant->get_constval().bigintval != 0LL &&
558 (rhs_constant->get_constval().bigintval %
exp_to_scale(rhs_type.get_scale())) ==
561 }
else if (rhs_cast && rhs_cast->get_optype() ==
kCAST &&
562 rhs_cast->get_operand()->get_type_info().is_integer()) {
568 auto lhs_lv =
codegen(lhs,
true, co).front();
569 llvm::Value* rhs_lv{
nullptr};
572 rhs_constant->get_constval().bigintval /
exp_to_scale(rhs_type.get_scale()));
574 dynamic_cast<const Analyzer::Constant*>(rhs_lit.get()),
cgen_state_);
576 rhs_lit_lv, rhs_lit->get_type_info(), lhs_type,
false);
577 }
else if (rhs_cast) {
578 auto rhs_cast_oper = rhs_cast->get_operand();
579 const auto& rhs_cast_oper_ti = rhs_cast_oper->get_type_info();
580 auto rhs_cast_oper_lv =
codegen(rhs_cast_oper,
true, co).front();
582 rhs_cast_oper_lv, rhs_cast_oper_ti, lhs_type,
false);
590 null_check_suffix.empty() ?
"" : int_typename,
598 const std::string& null_typename,
599 const std::string& null_check_suffix,
602 CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
606 auto mod_ok = llvm::BasicBlock::Create(
608 auto mod_zero = llvm::BasicBlock::Create(
610 auto zero_const = llvm::ConstantInt::get(rhs_lv->getType(), 0,
true);
616 auto ret = null_typename.empty()
619 "mod_" + null_typename + null_check_suffix,
637 auto expr_range_info =
644 if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
658 llvm::Value* chosen_max{
nullptr};
659 llvm::Value* chosen_min{
nullptr};
660 bool need_overflow_check =
false;
661 if (ti.is_integer() || ti.is_decimal() || ti.is_timeinterval()) {
665 static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
666 static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
668 llvm::BasicBlock* uminus_ok{
nullptr};
669 llvm::BasicBlock* uminus_fail{
nullptr};
670 if (need_overflow_check) {
672 uminus_ok = llvm::BasicBlock::Create(
674 if (!ti.get_notnull()) {
677 uminus_fail = llvm::BasicBlock::Create(
679 auto const_min = llvm::ConstantInt::get(
680 operand_lv->getType(),
681 static_cast<llvm::ConstantInt*
>(chosen_min)->getSExtValue(),
696 if (need_overflow_check) {
708 llvm::Intrinsic::ID fn_id{llvm::Intrinsic::not_intrinsic};
711 fn_id = llvm::Intrinsic::ssub_with_overflow;
714 fn_id = llvm::Intrinsic::sadd_with_overflow;
717 fn_id = llvm::Intrinsic::smul_with_overflow;
720 LOG(
FATAL) <<
"unexpected arith with overflow optype: " << bin_oper->
toString();
730 const std::string& null_check_suffix,
735 llvm::BasicBlock* check_ok = llvm::BasicBlock::Create(
737 llvm::BasicBlock* check_fail = llvm::BasicBlock::Create(
739 llvm::BasicBlock* null_check{
nullptr};
741 if (!null_check_suffix.empty()) {
749 func, std::vector<llvm::Value*>{lhs_lv, rhs_lv});
751 std::vector<unsigned>{0});
753 std::vector<unsigned>{1});
769 phi->addIncoming(ret, val_bb);
llvm::Value * codegenIntArith(const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const CompilationOptions &)
HOST DEVICE int get_size() const
llvm::Value * codegenArith(const Analyzer::BinOper *, const CompilationOptions &)
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
HOST DEVICE int get_scale() const
const Expr * get_right_operand() const
llvm::Value * codegenMod(llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &)
llvm::IRBuilder ir_builder_
llvm::Value * codegenDeciDiv(const Analyzer::BinOper *, const CompilationOptions &)
HOST DEVICE SQLTypes get_type() const
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string toString() const override
llvm::Value * codegenFpArith(const Analyzer::BinOper *, llvm::Value *, llvm::Value *)
SQLOps get_optype() const
static const int32_t ERR_DIV_BY_ZERO
llvm::LLVMContext & context_
llvm::Function * current_func_
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)
Classes representing a parse tree.
bool is_temporary_column(const Analyzer::Expr *expr)
void codegenSkipOverflowCheckForNull(llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
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
bool is_timeinterval() const
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
const std::vector< InputTableInfo > & query_infos_
llvm::ConstantFP * llFp(const float v) const
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)
const SQLTypeInfo & get_type_info() const
llvm::Value * codegenUMinus(const Analyzer::UOper *, const CompilationOptions &)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
static llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant, CgenState *cgen_state)
const shared::ColumnKey & getColumnKey() const
const Expr * get_operand() const
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 &)
llvm::Value * toBool(llvm::Value *)
llvm::ConstantInt * llInt(const T v) const
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
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
std::string numeric_type_name(const SQLTypeInfo &ti)
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)
HOST DEVICE bool get_notnull() const
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)
SQLOps get_optype() const
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Executor * executor() const