22 using namespace DateTimeUtils;
29 return "extract_epoch";
31 return "extract_dateepoch";
33 return "extract_quarterday";
35 return "extract_hour";
37 return "extract_minute";
39 return "extract_second";
41 return "extract_millisecond";
43 return "extract_microsecond";
45 return "extract_nanosecond";
49 return "extract_isodow";
53 return "extract_week_monday";
55 return "extract_week_sunday";
57 return "extract_week_saturday";
59 return "extract_day_of_year";
61 return "extract_month";
63 return "extract_quarter";
65 return "extract_year";
79 auto from_expr = codegen(extract_expr->
get_from_expr(),
true, co).front();
80 const int32_t extract_field{extract_expr->
get_field()};
82 if (extract_field ==
kEPOCH) {
84 extract_expr_ti.get_type() ==
kDATE);
85 if (from_expr->getType()->isIntegerTy(32)) {
87 cgen_state_->ir_builder_.CreateCast(llvm::Instruction::CastOps::SExt,
93 CHECK(from_expr->getType()->isIntegerTy(64));
94 if (extract_expr_ti.is_high_precision_timestamp()) {
95 from_expr = codegenExtractHighPrecisionTimestamps(
96 from_expr, extract_expr_ti, extract_expr->
get_field());
98 if (!extract_expr_ti.is_high_precision_timestamp() &&
101 extract_expr_ti.get_notnull()
102 ? cgen_state_->ir_builder_.CreateMul(
106 : cgen_state_->emitCall(
107 "mul_int64_t_nullable_lhs",
111 cgen_state_->inlineIntNull(extract_expr_ti)});
114 if (!extract_expr_ti.get_notnull()) {
115 llvm::BasicBlock* extract_nullcheck_bb{
nullptr};
116 llvm::PHINode* extract_nullcheck_value{
nullptr};
119 llvm::ICmpInst::ICMP_EQ,
121 cgen_state_->inlineIntNull(extract_expr_ti)),
128 extract_nullcheck_bb = llvm::BasicBlock::Create(
129 cgen_state_->context_,
"extract_nullcheck_bb", cgen_state_->current_func_);
133 cgen_state_->ir_builder_.SetInsertPoint(null_check.cond_true_);
134 cgen_state_->ir_builder_.CreateBr(extract_nullcheck_bb);
135 cgen_state_->ir_builder_.SetInsertPoint(null_check.cond_false_);
137 cgen_state_->emitExternalCall(extract_fname,
139 std::vector<llvm::Value*>{from_expr});
140 cgen_state_->ir_builder_.CreateBr(extract_nullcheck_bb);
142 cgen_state_->ir_builder_.SetInsertPoint(extract_nullcheck_bb);
143 extract_nullcheck_value = cgen_state_->ir_builder_.CreatePHI(
144 get_int_type(64, cgen_state_->context_), 2,
"extract_value");
145 extract_nullcheck_value->addIncoming(extract_call, null_check.cond_false_);
146 extract_nullcheck_value->addIncoming(cgen_state_->inlineIntNull(extract_expr_ti),
147 null_check.cond_true_);
152 CHECK(extract_nullcheck_bb);
153 cgen_state_->ir_builder_.SetInsertPoint(extract_nullcheck_bb);
154 CHECK(extract_nullcheck_value);
155 return extract_nullcheck_value;
157 return cgen_state_->emitExternalCall(extract_fname,
159 std::vector<llvm::Value*>{from_expr});
169 CHECK(datetime->getType()->isIntegerTy(64));
173 std::vector<llvm::Value*> dateadd_args{
177 std::string dateadd_fname{
"DateAdd"};
179 dateadd_expr_ti.is_high_precision_timestamp()) {
180 dateadd_fname +=
"HighPrecision";
181 dateadd_args.push_back(
184 if (!datetime_ti.get_notnull()) {
189 dateadd_fname +=
"Nullable";
194 {llvm::Attribute::NoUnwind,
195 llvm::Attribute::ReadNone,
196 llvm::Attribute::Speculatable});
203 CHECK(start->getType()->isIntegerTy(64));
205 CHECK(end->getType()->isIntegerTy(32) || end->getType()->isIntegerTy(64));
208 std::vector<llvm::Value*> datediff_args{
210 std::string datediff_fname{
"DateDiff"};
211 if (start_ti.is_high_precision_timestamp() || end_ti.is_high_precision_timestamp()) {
212 datediff_fname +=
"HighPrecision";
213 datediff_args.push_back(
215 datediff_args.push_back(
219 if (!start_ti.get_notnull() || !end_ti.get_notnull()) {
221 datediff_fname +=
"Nullable";
232 CHECK(from_expr->getType()->isIntegerTy(64));
234 if (datetrunc_expr_ti.is_high_precision_timestamp()) {
245 std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
246 const bool is_nullable = !datetrunc_expr_ti.get_notnull();
248 nullcheck_codegen = std::make_unique<NullCheckCodegen>(
255 ret = nullcheck_codegen->finalize(
ll_int(
NULL_BIGINT, cgen_state_->context_), ret);
266 CHECK(ts_lv->getType()->isIntegerTy(64));
275 "mul_int64_t_nullable_lhs",
284 "floor_div_nullable_lhs",
292 return ti.get_notnull()
293 ? cgen_state_->ir_builder_.CreateSDiv(
295 cgen_state_->llInt(static_cast<int64_t>(
297 : cgen_state_->emitCall(
298 "floor_div_nullable_lhs",
301 cgen_state_->inlineIntNull(ti)});
309 constexpr int64_t pow10[10]{1, 0, 0, 1000, 0, 0, 1000000, 0, 0, 1000000000};
312 CHECK(ts_lv->getType()->isIntegerTy(64));
319 unsigned const trunc_dim = (field -
dtSECOND) * 3;
320 if (start_dim <= trunc_dim) {
323 int64_t
const dscale = pow10[start_dim - trunc_dim];
326 "floor_div_nullable_lhs",
329 "mul_int64_t_nullable_lhs",
339 "floor_div_nullable_lhs",
343 std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
345 nullcheck_codegen = std::make_unique<NullCheckCodegen>(
357 ? cgen_state_->emitCall(
358 "mul_int64_t_nullable_lhs",
359 {ts_lv, cgen_state_->llInt(scale), cgen_state_->inlineIntNull(ti)})
360 : cgen_state_->ir_builder_.CreateMul(ts_lv, cgen_state_->llInt(scale));
constexpr int64_t get_extract_timestamp_precision_scale(const ExtractField field)
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
llvm::IRBuilder ir_builder_
const char * get_extract_function_name(ExtractField field)
llvm::Value * codegenExtractHighPrecisionTimestamps(llvm::Value *, const SQLTypeInfo &, const ExtractField &)
DatetruncField get_field() const
const std::pair< SQLOps, int64_t > get_extract_high_precision_adjusted_scale(const ExtractField &field, const int32_t dimen)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
llvm::LLVMContext & context_
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value * > args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={}, const bool has_struct_return=false)
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
const Expr * get_start_expr() const
const SQLTypeInfo & get_type_info() const
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
constexpr std::array< char const *, dtINVALID > datetrunc_fname_lookup
const Expr * get_from_expr() const
const Expr * get_datetime_expr() const
HOST DEVICE int get_dimension() const
DateaddField get_field() const
constexpr bool is_subsecond_dateadd_field(const DateaddField field)
llvm::ConstantInt * llInt(const T v) const
const Expr * get_end_expr() const
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
bool is_high_precision_timestamp() const
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
int64_t inline_fixed_encoding_null_val(const SQL_TYPE_INFO &ti)
llvm::Value * codegenDateTruncHighPrecisionTimestamps(llvm::Value *, const SQLTypeInfo &, const DatetruncField &)
HOST DEVICE bool get_notnull() const
DatetruncField get_field() const
constexpr bool is_subsecond_extract_field(const ExtractField &field)
bool use_fixed_encoding_null_val() const
const Expr * get_number_expr() const
Executor * executor() const