OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CodeGenerator Class Reference

#include <CodeGenerator.h>

+ Inheritance diagram for CodeGenerator:
+ Collaboration diagram for CodeGenerator:

Classes

struct  ArgNullcheckBBs
 
struct  ExecutorRequired
 
struct  GPUTarget
 
struct  NullCheckCodegen
 

Public Member Functions

 CodeGenerator (Executor *executor)
 
 CodeGenerator (CgenState *cgen_state, PlanState *plan_state)
 
std::vector< llvm::Value * > codegen (const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
 
llvm::Value * codegenPerRowStringOper (const Analyzer::StringOper *string_oper, const CompilationOptions &co)
 
llvm::Value * codegenPseudoStringOper (const Analyzer::ColumnVar *, const std::vector< StringOps_Namespace::StringOpInfo > &string_op_infos, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenHoistedConstants (const std::vector< const Analyzer::Constant * > &constants, const EncodingType enc_type, const shared::StringDictKey &dict_id)
 
llvm::Value * codegenCastBetweenIntTypes (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
 
void codegenCastBetweenIntTypesOverflowChecks (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
 
llvm::Value * posArg (const Analyzer::Expr *) const
 
llvm::Value * toBool (llvm::Value *)
 
llvm::Value * castArrayPointer (llvm::Value *ptr, const SQLTypeInfo &elem_ti)
 
llvm::Value * codegenCastBetweenTimestamps (llvm::Value *ts_lv, const SQLTypeInfo &operand_dimen, const SQLTypeInfo &target_dimen, const bool nullable)
 
llvm::Value * codegenWindowPosition (const WindowFunctionContext *window_func_context, llvm::Value *pos_arg)
 

Static Public Member Functions

static llvm::ConstantInt * codegenIntConst (const Analyzer::Constant *constant, CgenState *cgen_state)
 
static std::unordered_set
< llvm::Function * > 
markDeadRuntimeFuncs (llvm::Module &module, const std::vector< llvm::Function * > &roots, const std::vector< llvm::Function * > &leaves)
 
static ExecutionEngineWrapper generateNativeCPUCode (llvm::Function *func, const std::unordered_set< llvm::Function * > &live_funcs, const CompilationOptions &co)
 
static std::string generatePTX (const std::string &cuda_llir, llvm::TargetMachine *nvptx_target_machine, llvm::LLVMContext &context)
 
static std::unique_ptr
< llvm::TargetMachine > 
initializeNVPTXBackend (const CudaMgr_Namespace::NvidiaDeviceArch arch)
 
static bool alwaysCloneRuntimeFunction (const llvm::Function *func)
 
static void linkModuleWithLibdevice (Executor *executor, llvm::Module &module, llvm::PassManagerBuilder &pass_manager_builder, const GPUTarget &gpu_target)
 
static std::shared_ptr
< GpuCompilationContext
generateNativeGPUCode (Executor *executor, llvm::Function *func, llvm::Function *wrapper_func, const std::unordered_set< llvm::Function * > &live_funcs, const bool is_gpu_smem_used, const CompilationOptions &co, const GPUTarget &gpu_target)
 
static void link_udf_module (const std::unique_ptr< llvm::Module > &udf_module, llvm::Module &module, CgenState *cgen_state, llvm::Linker::Flags flags=llvm::Linker::Flags::None)
 
static bool prioritizeQuals (const RelAlgExecutionUnit &ra_exe_unit, std::vector< Analyzer::Expr * > &primary_quals, std::vector< Analyzer::Expr * > &deferred_quals, const PlanState::HoistedFiltersSet &hoisted_quals)
 
static ArrayLoadCodegen codegenGeoArrayLoadAndNullcheck (llvm::Value *byte_stream, llvm::Value *pos, const SQLTypeInfo &ti, CgenState *cgen_state)
 

Protected Member Functions

Executorexecutor () const
 

Protected Attributes

CgenStatecgen_state_
 
PlanStateplan_state_
 

Private Member Functions

std::vector< llvm::Value * > codegen (const Analyzer::Constant *, const EncodingType enc_type, const shared::StringDictKey &dict_id, const CompilationOptions &)
 
virtual std::vector
< llvm::Value * > 
codegenColumn (const Analyzer::ColumnVar *, const bool fetch_column, const CompilationOptions &)
 
llvm::Value * codegenArith (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegenUMinus (const Analyzer::UOper *, const CompilationOptions &)
 
llvm::Value * codegenCmp (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegenCmp (const SQLOps, const SQLQualifier, std::vector< llvm::Value * >, const SQLTypeInfo &, const Analyzer::Expr *, const CompilationOptions &)
 
llvm::Value * codegenIsNull (const Analyzer::UOper *, const CompilationOptions &)
 
llvm::Value * codegenIsNullNumber (llvm::Value *, const SQLTypeInfo &)
 
llvm::Value * codegenLogical (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegenLogical (const Analyzer::UOper *, const CompilationOptions &)
 
llvm::Value * codegenCast (const Analyzer::UOper *, const CompilationOptions &)
 
llvm::Value * codegenCast (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const bool operand_is_const, const CompilationOptions &co)
 
llvm::Value * codegen (const Analyzer::InValues *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::InIntegerSet *expr, const CompilationOptions &co)
 
std::vector< llvm::Value * > codegen (const Analyzer::CaseExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::ExtractExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::DateaddExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::DatediffExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::DatetruncExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::CharLengthExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::KeyForStringExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::SampleRatioExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::WidthBucketExpr *, const CompilationOptions &)
 
llvm::Value * codegenConstantWidthBucketExpr (const Analyzer::WidthBucketExpr *, const CompilationOptions &)
 
llvm::Value * codegenWidthBucketExpr (const Analyzer::WidthBucketExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::MLPredictExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::PCAProjectExpr *, const CompilationOptions &)
 
llvm::Value * codegenLinRegPredict (const Analyzer::MLPredictExpr *, const std::shared_ptr< AbstractMLModel > &model, const CompilationOptions &)
 
llvm::Value * codegenTreeRegPredict (const Analyzer::MLPredictExpr *, const std::shared_ptr< AbstractTreeModel > &tree_model, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::StringOper *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::LikeExpr *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::RegexpExpr *, const CompilationOptions &)
 
llvm::Value * codegenUnnest (const Analyzer::UOper *, const CompilationOptions &)
 
llvm::Value * codegenArrayAt (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::CardinalityExpr *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenArrayExpr (const Analyzer::ArrayExpr *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeoColumnVar (const Analyzer::GeoColumnVar *, const bool fetch_columns, const CompilationOptions &co)
 
std::vector< llvm::Value * > codegenGeoExpr (const Analyzer::GeoExpr *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeoConstant (const Analyzer::GeoConstant *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeoOperator (const Analyzer::GeoOperator *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeoUOper (const Analyzer::GeoUOper *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeoBinOper (const Analyzer::GeoBinOper *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeosPredicateCall (const std::string &, std::vector< llvm::Value * >, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeosConstructorCall (const std::string &, std::vector< llvm::Value * >, llvm::Value *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenGeoArgs (const std::vector< std::shared_ptr< Analyzer::Expr >> &, const CompilationOptions &)
 
llvm::Value * codegenFunctionOper (const Analyzer::FunctionOper *, const CompilationOptions &)
 
llvm::Value * codegenFunctionOperWithCustomTypeHandling (const Analyzer::FunctionOperWithCustomTypeHandling *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegen (const Analyzer::UOper *, const CompilationOptions &)
 
std::vector< llvm::Value * > codegenHoistedConstantsLoads (const SQLTypeInfo &type_info, const EncodingType enc_type, const shared::StringDictKey &dict_id, const int16_t lit_off, const size_t lit_bytes)
 
std::vector< llvm::Value * > codegenHoistedConstantsPlaceholders (const SQLTypeInfo &type_info, const EncodingType enc_type, const int16_t lit_off, const std::vector< llvm::Value * > &literal_loads)
 
std::vector< llvm::Value * > codegenColVar (const Analyzer::ColumnVar *, const bool fetch_column, const bool update_query_plan, const CompilationOptions &)
 
llvm::Value * codegenFixedLengthColVar (const Analyzer::ColumnVar *col_var, llvm::Value *col_byte_stream, llvm::Value *pos_arg, const WindowFunctionContext *window_function_context=nullptr)
 
llvm::Value * codegenFixedLengthColVarInWindow (const Analyzer::ColumnVar *col_var, llvm::Value *col_byte_stream, llvm::Value *pos_arg, const CompilationOptions &co, const WindowFunctionContext *window_function_context=nullptr)
 
std::vector< llvm::Value * > codegenVariableLengthStringColVar (llvm::Value *col_byte_stream, llvm::Value *pos_arg)
 
llvm::Value * codegenRowId (const Analyzer::ColumnVar *col_var, const CompilationOptions &co)
 
llvm::Value * codgenAdjustFixedEncNull (llvm::Value *, const SQLTypeInfo &)
 
std::vector< llvm::Value * > codegenOuterJoinNullPlaceholder (const Analyzer::ColumnVar *col_var, const bool fetch_column, const CompilationOptions &co)
 
llvm::Value * codegenIntArith (const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const CompilationOptions &)
 
llvm::Value * codegenFpArith (const Analyzer::BinOper *, llvm::Value *, llvm::Value *)
 
llvm::Value * codegenCastTimestampToTime (llvm::Value *ts_lv, const int dimen, const bool nullable)
 
llvm::Value * codegenCastTimestampToDate (llvm::Value *ts_lv, const int dimen, const bool nullable)
 
llvm::Value * codegenCastFromString (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const bool operand_is_const, const CompilationOptions &co)
 
llvm::Value * codegenCastNonStringToString (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const bool operand_is_const, const CompilationOptions &co)
 
llvm::Value * codegenCastToFp (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
 
llvm::Value * codegenCastFromFp (llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
 
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 &)
 
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 &)
 
void codegenSkipOverflowCheckForNull (llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
 
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)
 
llvm::Value * codegenDiv (llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &, bool upscale=true)
 
llvm::Value * codegenDeciDiv (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegenMod (llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &)
 
llvm::Value * codegenCase (const Analyzer::CaseExpr *, llvm::Type *case_llvm_type, const bool is_real_str, const CompilationOptions &)
 
llvm::Value * codegenExtractHighPrecisionTimestamps (llvm::Value *, const SQLTypeInfo &, const ExtractField &)
 
llvm::Value * codegenDateTruncHighPrecisionTimestamps (llvm::Value *, const SQLTypeInfo &, const DatetruncField &)
 
llvm::Value * codegenCmpDecimalConst (const SQLOps, const SQLQualifier, const Analyzer::Expr *, const SQLTypeInfo &, const Analyzer::Expr *, const CompilationOptions &)
 
llvm::Value * codegenBoundingBoxIntersect (const SQLOps, const SQLQualifier, const std::shared_ptr< Analyzer::Expr >, const std::shared_ptr< Analyzer::Expr >, const CompilationOptions &)
 
llvm::Value * codegenStrCmp (const SQLOps, const SQLQualifier, const std::shared_ptr< Analyzer::Expr >, const std::shared_ptr< Analyzer::Expr >, const CompilationOptions &)
 
llvm::Value * codegenQualifierCmp (const SQLOps, const SQLQualifier, std::vector< llvm::Value * >, const Analyzer::Expr *, const CompilationOptions &)
 
llvm::Value * codegenLogicalShortCircuit (const Analyzer::BinOper *, const CompilationOptions &)
 
llvm::Value * codegenDictLike (const std::shared_ptr< Analyzer::Expr > arg, const Analyzer::Constant *pattern, const bool ilike, const bool is_simple, const char escape_char, const CompilationOptions &)
 
llvm::Value * codegenDictStrCmp (const std::shared_ptr< Analyzer::Expr >, const std::shared_ptr< Analyzer::Expr >, const SQLOps, const CompilationOptions &co)
 
llvm::Value * codegenDictRegexp (const std::shared_ptr< Analyzer::Expr > arg, const Analyzer::Constant *pattern, const char escape_char, const CompilationOptions &)
 
llvm::Value * foundOuterJoinMatch (const size_t nesting_level) const
 
llvm::Value * resolveGroupedColumnReference (const Analyzer::ColumnVar *)
 
llvm::Value * colByteStream (const Analyzer::ColumnVar *col_var, const bool fetch_column, const bool hoist_literals)
 
std::shared_ptr< const
Analyzer::Expr
hashJoinLhs (const Analyzer::ColumnVar *rhs) const
 
std::shared_ptr< const
Analyzer::ColumnVar
hashJoinLhsTuple (const Analyzer::ColumnVar *rhs, const Analyzer::BinOper *tautological_eq) const
 
bool needCastForHashJoinLhs (const Analyzer::ColumnVar *rhs) const
 
std::unique_ptr< InValuesBitmapcreateInValuesBitmap (const Analyzer::InValues *, const CompilationOptions &)
 
bool checkExpressionRanges (const Analyzer::UOper *, int64_t, int64_t)
 
bool checkExpressionRanges (const Analyzer::BinOper *, int64_t, int64_t)
 
std::tuple< ArgNullcheckBBs,
llvm::Value * > 
beginArgsNullcheck (const Analyzer::FunctionOper *function_oper, const std::vector< llvm::Value * > &orig_arg_lvs)
 
llvm::Value * endArgsNullcheck (const ArgNullcheckBBs &, llvm::Value *, llvm::Value *, const Analyzer::FunctionOper *)
 
llvm::Value * codegenFunctionOperNullArg (const Analyzer::FunctionOper *, const std::vector< llvm::Value * > &)
 
llvm::Value * codegenCompression (const SQLTypeInfo &type_info)
 
std::pair< llvm::Value
*, llvm::Value * > 
codegenArrayBuff (llvm::Value *chunk, llvm::Value *row_pos, SQLTypes array_type, bool cast_and_extend)
 
void codegenBufferArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *buffer_buf, llvm::Value *buffer_size, llvm::Value *buffer_is_null, std::vector< llvm::Value * > &output_args)
 
llvm::StructType * createPointStructType (const std::string &udf_func_name, size_t param_num)
 
void codegenGeoPointArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *point_buf, llvm::Value *point_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
 
llvm::StructType * createMultiPointStructType (const std::string &udf_func_name, size_t param_num)
 
void codegenGeoMultiPointArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *multi_point_buf, llvm::Value *multi_point_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
 
llvm::StructType * createLineStringStructType (const std::string &udf_func_name, size_t param_num)
 
void codegenGeoLineStringArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *line_string_buf, llvm::Value *line_string_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
 
llvm::StructType * createMultiLineStringStructType (const std::string &udf_func_name, size_t param_num)
 
void codegenGeoMultiLineStringArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *multi_linestring_coords, llvm::Value *multi_linestring_size, llvm::Value *linestring_sizes, llvm::Value *linestring_sizes_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
 
llvm::StructType * createPolygonStructType (const std::string &udf_func_name, size_t param_num)
 
void codegenGeoPolygonArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *polygon_buf, llvm::Value *polygon_size, llvm::Value *ring_sizes_buf, llvm::Value *num_rings, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
 
llvm::StructType * createMultiPolygonStructType (const std::string &udf_func_name, size_t param_num)
 
void codegenGeoMultiPolygonArgs (const std::string &udf_func_name, size_t param_num, llvm::Value *polygon_coords, llvm::Value *polygon_coords_size, llvm::Value *ring_sizes_buf, llvm::Value *ring_sizes, llvm::Value *polygon_bounds, llvm::Value *polygon_bounds_sizes, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
 
std::vector< llvm::Value * > codegenFunctionOperCastArgs (const Analyzer::FunctionOper *, const ExtensionFunction *, const std::vector< llvm::Value * > &, const std::vector< size_t > &, const std::unordered_map< llvm::Value *, llvm::Value * > &, const CompilationOptions &)
 
llvm::StructType * createStringViewStructType ()
 
llvm::Function * getArithWithOverflowIntrinsic (const Analyzer::BinOper *bin_oper, llvm::Type *type)
 
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)
 
std::pair< std::vector
< llvm::Value * >
, std::unique_ptr
< CodeGenerator::NullCheckCodegen > > 
codegenStringFetchAndEncode (const Analyzer::StringOper *expr, const CompilationOptions &co, const size_t arg_idx, const bool codegen_nullcheck)
 

Private Attributes

Executorexecutor_
 

Static Private Attributes

static std::mutex initialize_nvptx_mutex_
 
static std::mutex initialize_cpu_backend_mutex_
 

Friends

class GroupByAndAggregate
 

Detailed Description

Definition at line 29 of file CodeGenerator.h.

Constructor & Destructor Documentation

CodeGenerator::CodeGenerator ( Executor executor)
inline

Definition at line 31 of file CodeGenerator.h.

33  , cgen_state_(executor->cgen_state_.get())
34  , plan_state_(executor->plan_state_.get()) {}
CgenState * cgen_state_
Executor * executor_
PlanState * plan_state_
Executor * executor() const
CodeGenerator::CodeGenerator ( CgenState cgen_state,
PlanState plan_state 
)
inline

Definition at line 38 of file CodeGenerator.h.

39  : executor_(nullptr), cgen_state_(cgen_state), plan_state_(plan_state) {}
CgenState * cgen_state_
Executor * executor_
PlanState * plan_state_

Member Function Documentation

bool CodeGenerator::alwaysCloneRuntimeFunction ( const llvm::Function *  func)
static

Definition at line 1574 of file NativeCodegen.cpp.

Referenced by CgenState::set_module_shallow_copy().

1574  {
1575  auto const candidate_func_name = func->getName().str();
1578  [candidate_func_name](std::string_view func_name) {
1579  return candidate_func_name == func_name;
1580  });
1581 }
bool any_of(std::vector< Analyzer::Expr * > const &target_exprs)
constexpr std::array< std::string_view, 18 > TARGET_RUNTIME_FUNCTIONS_FOR_MODULE_CLONING

+ Here is the caller graph for this function:

std::tuple< CodeGenerator::ArgNullcheckBBs, llvm::Value * > CodeGenerator::beginArgsNullcheck ( const Analyzer::FunctionOper function_oper,
const std::vector< llvm::Value * > &  orig_arg_lvs 
)
private

Definition at line 428 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenFunctionOperNullArg(), CgenState::context_, CgenState::current_func_, anonymous_namespace{ExtensionsIR.cpp}::ext_func_call_requires_nullcheck(), anonymous_namespace{ExtensionsIR.cpp}::get_buffer_struct_type(), anonymous_namespace{ExtensionsIR.cpp}::get_llvm_type_from_sql_array_type(), Analyzer::Expr::get_type_info(), Analyzer::FunctionOper::getName(), and CgenState::ir_builder_.

Referenced by codegenFunctionOper(), and codegenFunctionOperWithCustomTypeHandling().

429  {
431  llvm::BasicBlock* args_null_bb{nullptr};
432  llvm::BasicBlock* args_notnull_bb{nullptr};
433  llvm::BasicBlock* orig_bb = cgen_state_->ir_builder_.GetInsertBlock();
434  llvm::Value* null_array_alloca{nullptr};
435  // Only generate the check if required (at least one argument must be nullable).
436  if (ext_func_call_requires_nullcheck(function_oper)) {
437  const auto func_ti = function_oper->get_type_info();
438  if (func_ti.is_buffer()) {
439  const auto arr_struct_ty = get_buffer_struct_type(
440  cgen_state_,
441  function_oper->getName(),
442  0,
444  null_array_alloca = cgen_state_->ir_builder_.CreateAlloca(arr_struct_ty);
445  }
446  const auto args_notnull_lv = cgen_state_->ir_builder_.CreateNot(
447  codegenFunctionOperNullArg(function_oper, orig_arg_lvs));
448  args_notnull_bb = llvm::BasicBlock::Create(
449  cgen_state_->context_, "args_notnull", cgen_state_->current_func_);
450  args_null_bb = llvm::BasicBlock::Create(
452  cgen_state_->ir_builder_.CreateCondBr(args_notnull_lv, args_notnull_bb, args_null_bb);
453  cgen_state_->ir_builder_.SetInsertPoint(args_notnull_bb);
454  }
455  return std::make_tuple(
456  CodeGenerator::ArgNullcheckBBs{args_null_bb, args_notnull_bb, orig_bb},
457  null_array_alloca);
458 }
CgenState * cgen_state_
llvm::Value * codegenFunctionOperNullArg(const Analyzer::FunctionOper *, const std::vector< llvm::Value * > &)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
bool ext_func_call_requires_nullcheck(const Analyzer::FunctionOper *function_oper)
llvm::StructType * get_buffer_struct_type(CgenState *cgen_state, const std::string &ext_func_name, size_t param_num, llvm::Type *elem_type)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
llvm::Type * get_llvm_type_from_sql_array_type(const SQLTypeInfo ti, llvm::LLVMContext &ctx)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::string getName() const
Definition: Analyzer.h:2744

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::castArrayPointer ( llvm::Value *  ptr,
const SQLTypeInfo elem_ti 
)

Definition at line 1748 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, SQLTypeInfo::get_compression(), SQLTypeInfo::get_size(), SQLTypeInfo::get_type(), CgenState::ir_builder_, SQLTypeInfo::is_boolean(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_string(), kDOUBLE, kENCODING_DICT, and kFLOAT.

Referenced by codegenFunctionOperCastArgs(), RangeJoinHashTable::codegenKey(), and BoundingBoxIntersectJoinHashTable::codegenKey().

1749  {
1751  if (elem_ti.get_type() == kFLOAT) {
1752  return cgen_state_->ir_builder_.CreatePointerCast(
1753  ptr, llvm::Type::getFloatPtrTy(cgen_state_->context_));
1754  }
1755  if (elem_ti.get_type() == kDOUBLE) {
1756  return cgen_state_->ir_builder_.CreatePointerCast(
1757  ptr, llvm::Type::getDoublePtrTy(cgen_state_->context_));
1758  }
1759  CHECK(elem_ti.is_integer() || elem_ti.is_boolean() ||
1760  (elem_ti.is_string() && elem_ti.get_compression() == kENCODING_DICT));
1761  switch (elem_ti.get_size()) {
1762  case 1:
1763  return cgen_state_->ir_builder_.CreatePointerCast(
1764  ptr, llvm::Type::getInt8PtrTy(cgen_state_->context_));
1765  case 2:
1766  return cgen_state_->ir_builder_.CreatePointerCast(
1767  ptr, llvm::Type::getInt16PtrTy(cgen_state_->context_));
1768  case 4:
1769  return cgen_state_->ir_builder_.CreatePointerCast(
1770  ptr, llvm::Type::getInt32PtrTy(cgen_state_->context_));
1771  case 8:
1772  return cgen_state_->ir_builder_.CreatePointerCast(
1773  ptr, llvm::Type::getInt64PtrTy(cgen_state_->context_));
1774  default:
1775  CHECK(false);
1776  }
1777  return nullptr;
1778 }
HOST DEVICE int get_size() const
Definition: sqltypes.h:403
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::LLVMContext & context_
Definition: CgenState.h:382
bool is_integer() const
Definition: sqltypes.h:567
bool is_boolean() const
Definition: sqltypes.h:582
#define AUTOMATIC_IR_METADATA(CGENSTATE)
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
#define CHECK(condition)
Definition: Logger.h:291
bool is_string() const
Definition: sqltypes.h:561

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool CodeGenerator::checkExpressionRanges ( const Analyzer::UOper uoper,
int64_t  min,
int64_t  max 
)
private

Definition at line 630 of file ArithmeticIR.cpp.

References CHECK, executor(), executor_, Analyzer::Expr::get_type_info(), getExpressionRange(), Integer, SQLTypeInfo::is_decimal(), ExpressionRange::makeInvalidRange(), plan_state_, and PlanState::query_infos_.

Referenced by codegenAdd(), codegenMul(), codegenSub(), and codegenUMinus().

632  {
633  if (uoper->get_type_info().is_decimal()) {
634  return false;
635  }
636 
638  if (executor_) {
639  auto expr_range_info =
640  plan_state_->query_infos_.size() > 0
642  : ExpressionRange::makeInvalidRange();
643  if (expr_range_info.getType() != ExpressionRangeType::Integer) {
644  return false;
645  }
646  if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
647  return true;
648  }
649  }
650 
651  return false;
652 }
Executor * executor_
const std::vector< InputTableInfo > & query_infos_
Definition: PlanState.h:65
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)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
PlanState * plan_state_
#define CHECK(condition)
Definition: Logger.h:291
bool is_decimal() const
Definition: sqltypes.h:570
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool CodeGenerator::checkExpressionRanges ( const Analyzer::BinOper bin_oper,
int64_t  min,
int64_t  max 
)
private

Definition at line 189 of file ArithmeticIR.cpp.

References CHECK, executor(), executor_, Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), getExpressionRange(), Integer, SQLTypeInfo::is_decimal(), anonymous_namespace{ArithmeticIR.cpp}::is_temporary_column(), ExpressionRange::makeInvalidRange(), plan_state_, and PlanState::query_infos_.

191  {
192  if (is_temporary_column(bin_oper->get_left_operand()) ||
193  is_temporary_column(bin_oper->get_right_operand())) {
194  // Computing the range for temporary columns is a lot more expensive than the overflow
195  // check.
196  return false;
197  }
198  if (bin_oper->get_type_info().is_decimal()) {
199  return false;
200  }
201 
203  if (executor_) {
204  auto expr_range_info =
205  plan_state_->query_infos_.size() > 0
207  : ExpressionRange::makeInvalidRange();
208  if (expr_range_info.getType() != ExpressionRangeType::Integer) {
209  return false;
210  }
211  if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
212  return true;
213  }
214  }
215 
216  return false;
217 }
const Expr * get_right_operand() const
Definition: Analyzer.h:456
bool is_temporary_column(const Analyzer::Expr *expr)
Executor * executor_
const std::vector< InputTableInfo > & query_infos_
Definition: PlanState.h:65
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)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
PlanState * plan_state_
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455
bool is_decimal() const
Definition: sqltypes.h:570
Executor * executor() const

+ Here is the call graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegen ( const Analyzer::Expr expr,
const bool  fetch_columns,
const CompilationOptions co 
)

Definition at line 30 of file IRCodegen.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_NE, codegenArrayExpr(), codegenColumn(), codegenFunctionOper(), codegenFunctionOperWithCustomTypeHandling(), codegenGeoBinOper(), codegenGeoColumnVar(), codegenGeoExpr(), codegenGeoUOper(), CgenState::context_, createStringViewStructType(), executor_, get_int_type(), Analyzer::Expr::get_type_info(), CgenState::ir_builder_, kENCODING_DICT, kENCODING_NONE, kLINESTRING, kMULTILINESTRING, kMULTIPOINT, kMULTIPOLYGON, kNULLT, kPOINT, kPOLYGON, CgenState::llInt(), posArg(), and width_bucket_expr().

Referenced by Executor::buildHoistLeftHandSideFiltersCb(), Executor::buildIsDeletedCb(), Executor::buildJoinLoops(), TreeModelPredictionMgr::codegen(), codegen(), GroupByAndAggregate::codegenAggArg(), TargetExprCodegen::codegenAggregate(), codegenArith(), codegenArrayAt(), codegenArrayExpr(), codegenCase(), codegenCast(), codegenCmp(), codegenCmpDecimalConst(), HashJoin::codegenColOrStringOper(), codegenColVar(), codegenConstantWidthBucketExpr(), codegenDeciDiv(), codegenDictLike(), codegenDictRegexp(), codegenDictStrCmp(), Executor::codegenFrameBoundExpr(), codegenFunctionOper(), codegenFunctionOperWithCustomTypeHandling(), codegenGeoArgs(), codegenGeoColumnVar(), codegenGeoConstant(), codegenGeoOperator(), codegenIsNull(), RangeJoinHashTable::codegenKey(), BoundingBoxIntersectJoinHashTable::codegenKey(), codegenLogical(), codegenLogicalShortCircuit(), BoundingBoxIntersectJoinHashTable::codegenManyKey(), codegenOuterJoinNullPlaceholder(), GroupByAndAggregate::codegenOutputSlot(), codegenPseudoStringOper(), codegenQualifierCmp(), codegenRowId(), codegenStringFetchAndEncode(), codegenTreeRegPredict(), codegenUMinus(), codegenUnnest(), codegenWidthBucketExpr(), Executor::codegenWindowFunctionAggregateCalls(), ScalarCodeGenerator::compile(), and Executor::groupByColumnCodegen().

32  {
34  if (!expr) {
35  return {posArg(expr)};
36  }
37  auto bin_oper = dynamic_cast<const Analyzer::BinOper*>(expr);
38  if (bin_oper) {
39  return {codegen(bin_oper, co)};
40  }
41  auto u_oper = dynamic_cast<const Analyzer::UOper*>(expr);
42  if (u_oper) {
43  return {codegen(u_oper, co)};
44  }
45  auto geo_col_var = dynamic_cast<const Analyzer::GeoColumnVar*>(expr);
46  if (geo_col_var) {
47  // inherits from ColumnVar, so it is important we check this first
48  return codegenGeoColumnVar(geo_col_var, fetch_columns, co);
49  }
50  auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(expr);
51  if (col_var) {
52  return codegenColumn(col_var, fetch_columns, co);
53  }
54  auto constant = dynamic_cast<const Analyzer::Constant*>(expr);
55  if (constant) {
56  const auto& ti = constant->get_type_info();
57  if (ti.get_type() == kNULLT) {
58  throw std::runtime_error(
59  "NULL type literals are not currently supported in this context.");
60  }
61  if (constant->get_is_null()) {
62  const auto i8p_ty =
63  llvm::PointerType::get(get_int_type(8, executor_->cgen_state_->context_), 0);
64  if (ti.is_string() && ti.get_compression() == kENCODING_NONE) {
65  std::vector<llvm::Value*> null_target_lvs;
66  llvm::StructType* str_view_ty = createStringViewStructType();
67  auto null_str_view_struct_lv = cgen_state_->ir_builder_.CreateAlloca(str_view_ty);
68  // we do not need to fill the values of the string_view struct representing null
69  // string
70  null_target_lvs.push_back(
71  cgen_state_->ir_builder_.CreateLoad(str_view_ty, null_str_view_struct_lv));
72  null_target_lvs.push_back(llvm::ConstantPointerNull::get(
73  llvm::PointerType::get(llvm::IntegerType::get(cgen_state_->context_, 8), 0)));
74  null_target_lvs.push_back(cgen_state_->llInt((int32_t)0));
75  return null_target_lvs;
76  } else if (ti.is_geometry()) {
77  std::vector<llvm::Value*> ret_lvs;
78  // we classify whether the geo col value is null from the rhs of the left-join
79  // qual i.e., table S in the qual: R left join S on R.v = S.v by checking 1)
80  // nulled chunk_iter and 2) its col buffer w/ the size 0 for instance, we consider
81  // the size of col buffer for point as 16 and for other types we use `array_size`
82  // function to determine it, and they all assume valid geos have their buf size >
83  // 0 thus, by returning all bufs' ptr as nullptr we can return 0 as the length of
84  // the nulled geos' col val, and remaining logic can exploit this to finally
85  // return "null" as the col value of the corresponding row in the resultset
86  switch (ti.get_type()) {
87  // outer join's phi node in the generated code expects the # returned lvs'
88  // is the same as `col_ti.get_physical_coord_cols()`
89  // now we have necessary logic to deal with these nullptr and can conclude
90  // it as nulled geo val, i.e., see ResultSetIteration::991
91  case kPOINT:
92  case kMULTIPOINT:
93  case kLINESTRING:
94  return {llvm::ConstantPointerNull::get(i8p_ty)};
95  case kMULTILINESTRING:
96  case kPOLYGON:
97  return {llvm::ConstantPointerNull::get(i8p_ty),
98  llvm::ConstantPointerNull::get(i8p_ty)};
99  case kMULTIPOLYGON:
100  return {llvm::ConstantPointerNull::get(i8p_ty),
101  llvm::ConstantPointerNull::get(i8p_ty),
102  llvm::ConstantPointerNull::get(i8p_ty)};
103  default:
104  CHECK(false);
105  return {nullptr};
106  }
107  } else if (ti.is_array()) {
108  // similar to above nulled geo case, we can use this `nullptr` to guide
109  // `array_buff` and `array_size` functions representing nulled array value
110  return {llvm::ConstantPointerNull::get(i8p_ty)};
111  }
112  return {ti.is_fp()
113  ? static_cast<llvm::Value*>(executor_->cgen_state_->inlineFpNull(ti))
114  : static_cast<llvm::Value*>(executor_->cgen_state_->inlineIntNull(ti))};
115  }
116  if (ti.get_compression() == kENCODING_DICT) {
117  // The dictionary encoding case should be handled by the parent expression
118  // (cast, for now), here is too late to know the dictionary id if not already set
119  CHECK_NE(ti.getStringDictKey().dict_id, 0);
120  return {codegen(constant, ti.get_compression(), ti.getStringDictKey(), co)};
121  }
122  return {codegen(constant, ti.get_compression(), {}, co)};
123  }
124  auto case_expr = dynamic_cast<const Analyzer::CaseExpr*>(expr);
125  if (case_expr) {
126  return {codegen(case_expr, co)};
127  }
128  auto extract_expr = dynamic_cast<const Analyzer::ExtractExpr*>(expr);
129  if (extract_expr) {
130  return {codegen(extract_expr, co)};
131  }
132  auto dateadd_expr = dynamic_cast<const Analyzer::DateaddExpr*>(expr);
133  if (dateadd_expr) {
134  return {codegen(dateadd_expr, co)};
135  }
136  auto datediff_expr = dynamic_cast<const Analyzer::DatediffExpr*>(expr);
137  if (datediff_expr) {
138  return {codegen(datediff_expr, co)};
139  }
140  auto datetrunc_expr = dynamic_cast<const Analyzer::DatetruncExpr*>(expr);
141  if (datetrunc_expr) {
142  return {codegen(datetrunc_expr, co)};
143  }
144  auto charlength_expr = dynamic_cast<const Analyzer::CharLengthExpr*>(expr);
145  if (charlength_expr) {
146  return {codegen(charlength_expr, co)};
147  }
148  auto keyforstring_expr = dynamic_cast<const Analyzer::KeyForStringExpr*>(expr);
149  if (keyforstring_expr) {
150  return {codegen(keyforstring_expr, co)};
151  }
152  auto sample_ratio_expr = dynamic_cast<const Analyzer::SampleRatioExpr*>(expr);
153  if (sample_ratio_expr) {
154  return {codegen(sample_ratio_expr, co)};
155  }
156  auto string_oper_expr = dynamic_cast<const Analyzer::StringOper*>(expr);
157  if (string_oper_expr) {
158  return {codegen(string_oper_expr, co)};
159  }
160  auto cardinality_expr = dynamic_cast<const Analyzer::CardinalityExpr*>(expr);
161  if (cardinality_expr) {
162  return {codegen(cardinality_expr, co)};
163  }
164  auto like_expr = dynamic_cast<const Analyzer::LikeExpr*>(expr);
165  if (like_expr) {
166  return {codegen(like_expr, co)};
167  }
168  auto regexp_expr = dynamic_cast<const Analyzer::RegexpExpr*>(expr);
169  if (regexp_expr) {
170  return {codegen(regexp_expr, co)};
171  }
172  auto width_bucket_expr = dynamic_cast<const Analyzer::WidthBucketExpr*>(expr);
173  if (width_bucket_expr) {
174  return {codegen(width_bucket_expr, co)};
175  }
176 
177  auto ml_predict_expr = dynamic_cast<const Analyzer::MLPredictExpr*>(expr);
178  if (ml_predict_expr) {
179  return {codegen(ml_predict_expr, co)};
180  }
181 
182  auto pca_project_expr = dynamic_cast<const Analyzer::PCAProjectExpr*>(expr);
183  if (pca_project_expr) {
184  return {codegen(pca_project_expr, co)};
185  }
186 
187  auto likelihood_expr = dynamic_cast<const Analyzer::LikelihoodExpr*>(expr);
188  if (likelihood_expr) {
189  return {codegen(likelihood_expr->get_arg(), fetch_columns, co)};
190  }
191  auto in_expr = dynamic_cast<const Analyzer::InValues*>(expr);
192  if (in_expr) {
193  return {codegen(in_expr, co)};
194  }
195  auto in_integer_set_expr = dynamic_cast<const Analyzer::InIntegerSet*>(expr);
196  if (in_integer_set_expr) {
197  return {codegen(in_integer_set_expr, co)};
198  }
199  auto function_oper_with_custom_type_handling_expr =
200  dynamic_cast<const Analyzer::FunctionOperWithCustomTypeHandling*>(expr);
201  if (function_oper_with_custom_type_handling_expr) {
203  function_oper_with_custom_type_handling_expr, co)};
204  }
205  auto array_oper_expr = dynamic_cast<const Analyzer::ArrayExpr*>(expr);
206  if (array_oper_expr) {
207  return {codegenArrayExpr(array_oper_expr, co)};
208  }
209  auto geo_uop = dynamic_cast<const Analyzer::GeoUOper*>(expr);
210  if (geo_uop) {
211  return {codegenGeoUOper(geo_uop, co)};
212  }
213  auto geo_binop = dynamic_cast<const Analyzer::GeoBinOper*>(expr);
214  if (geo_binop) {
215  return {codegenGeoBinOper(geo_binop, co)};
216  }
217  auto function_oper_expr = dynamic_cast<const Analyzer::FunctionOper*>(expr);
218  if (function_oper_expr) {
219  return {codegenFunctionOper(function_oper_expr, co)};
220  }
221  auto geo_expr = dynamic_cast<const Analyzer::GeoExpr*>(expr);
222  if (geo_expr) {
223  return codegenGeoExpr(geo_expr, co);
224  }
225  if (dynamic_cast<const Analyzer::OffsetInFragment*>(expr)) {
226  return {posArg(nullptr)};
227  }
228  if (dynamic_cast<const Analyzer::WindowFunction*>(expr)) {
229  throw NativeExecutionError("Window expression not supported in this context");
230  }
231  abort();
232 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
virtual std::vector< llvm::Value * > codegenColumn(const Analyzer::ColumnVar *, const bool fetch_column, const CompilationOptions &)
Definition: ColumnIR.cpp:94
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::vector< llvm::Value * > codegenGeoBinOper(const Analyzer::GeoBinOper *, const CompilationOptions &)
Definition: GeoIR.cpp:263
std::vector< llvm::Value * > codegenGeoExpr(const Analyzer::GeoExpr *, const CompilationOptions &)
Definition: GeoIR.cpp:97
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define CHECK_NE(x, y)
Definition: Logger.h:302
std::vector< llvm::Value * > codegenGeoUOper(const Analyzer::GeoUOper *, const CompilationOptions &)
Definition: GeoIR.cpp:183
llvm::Value * codegenFunctionOper(const Analyzer::FunctionOper *, const CompilationOptions &)
Executor * executor_
std::vector< llvm::Value * > codegenArrayExpr(const Analyzer::ArrayExpr *, const CompilationOptions &)
Definition: ArrayIR.cpp:97
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Expression class for string functions The &quot;arg&quot; constructor parameter must be an expression that reso...
Definition: Analyzer.h:1601
llvm::StructType * createStringViewStructType()
std::vector< llvm::Value * > codegenGeoColumnVar(const Analyzer::GeoColumnVar *, const bool fetch_columns, const CompilationOptions &co)
Definition: GeoIR.cpp:54
llvm::Value * codegenFunctionOperWithCustomTypeHandling(const Analyzer::FunctionOperWithCustomTypeHandling *, const CompilationOptions &)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
RUNTIME_EXPORT ALWAYS_INLINE DEVICE int32_t width_bucket_expr(const double target_value, const bool reversed, const double lower_bound, const double upper_bound, const int32_t partition_count)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegen ( const Analyzer::Constant constant,
const EncodingType  enc_type,
const shared::StringDictKey dict_id,
const CompilationOptions co 
)
private

Definition at line 20 of file ConstantIR.cpp.

References CgenState::addStringConstant(), AUTOMATIC_IR_METADATA, Datum::boolval, cgen_state_, CHECK, codegenGeoConstant(), codegenHoistedConstants(), codegenIntConst(), CgenState::context_, decimal_to_int_type(), CompilationOptions::device_type, Datum::doubleval, executor(), Datum::floatval, Analyzer::Constant::get_constval(), get_int_type(), Analyzer::Constant::get_is_null(), Analyzer::Expr::get_type_info(), CompilationOptions::hoist_literals, inline_int_null_val(), kBIGINT, kBOOLEAN, kCHAR, kDATE, kDOUBLE, kENCODING_DICT, kFLOAT, kINT, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kSMALLINT, kTEXT, kTIME, kTIMESTAMP, kTINYINT, kVARCHAR, CgenState::llInt(), Datum::stringval, and run_benchmark_import::type.

23  {
25  if (co.hoist_literals) {
26  if (const auto geo_constant = dynamic_cast<const Analyzer::GeoConstant*>(constant)) {
27  return codegenGeoConstant(geo_constant, co);
28  } else {
29  std::vector<const Analyzer::Constant*> constants(
30  executor()->deviceCount(co.device_type), constant);
31  return codegenHoistedConstants(constants, enc_type, dict_id);
32  }
33  }
34  const auto& type_info = constant->get_type_info();
35  const auto type =
36  type_info.is_decimal() ? decimal_to_int_type(type_info) : type_info.get_type();
37  switch (type) {
38  case kBOOLEAN:
39  return {llvm::ConstantInt::get(get_int_type(8, cgen_state_->context_),
40  constant->get_constval().boolval)};
41  case kTINYINT:
42  case kSMALLINT:
43  case kINT:
44  case kBIGINT:
45  case kTIME:
46  case kTIMESTAMP:
47  case kDATE:
48  case kINTERVAL_DAY_TIME:
50  return {CodeGenerator::codegenIntConst(constant, cgen_state_)};
51  case kFLOAT:
52  return {llvm::ConstantFP::get(llvm::Type::getFloatTy(cgen_state_->context_),
53  constant->get_constval().floatval)};
54  case kDOUBLE:
55  return {llvm::ConstantFP::get(llvm::Type::getDoubleTy(cgen_state_->context_),
56  constant->get_constval().doubleval)};
57  case kVARCHAR:
58  case kCHAR:
59  case kTEXT: {
60  CHECK(constant->get_constval().stringval || constant->get_is_null());
61  if (constant->get_is_null()) {
62  if (enc_type == kENCODING_DICT) {
63  return {
64  cgen_state_->llInt(static_cast<int32_t>(inline_int_null_val(type_info)))};
65  }
66  return {cgen_state_->llInt(int64_t(0)),
67  llvm::Constant::getNullValue(
68  llvm::PointerType::get(get_int_type(8, cgen_state_->context_), 0)),
69  cgen_state_->llInt(int32_t(0))};
70  }
71  const auto& str_const = *constant->get_constval().stringval;
72  if (enc_type == kENCODING_DICT) {
73  return {
75  ->getStringDictionaryProxy(
76  dict_id, executor()->getRowSetMemoryOwner(), true)
77  ->getIdOfString(str_const))};
78  }
79  return {cgen_state_->llInt(int64_t(0)),
80  cgen_state_->addStringConstant(str_const),
81  cgen_state_->llInt(static_cast<int32_t>(str_const.size()))};
82  }
83  default:
84  CHECK(false);
85  }
86  abort();
87 }
Definition: sqltypes.h:76
CgenState * cgen_state_
llvm::Value * addStringConstant(const std::string &str)
Definition: CgenState.h:190
int8_t boolval
Definition: Datum.h:72
bool get_is_null() const
Definition: Analyzer.h:347
std::vector< llvm::Value * > codegenHoistedConstants(const std::vector< const Analyzer::Constant * > &constants, const EncodingType enc_type, const shared::StringDictKey &dict_id)
Definition: ConstantIR.cpp:373
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
float floatval
Definition: Datum.h:77
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::string * stringval
Definition: Datum.h:81
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:561
ExecutorDeviceType device_type
Definition: sqltypes.h:79
Definition: sqltypes.h:80
static llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant, CgenState *cgen_state)
Definition: ConstantIR.cpp:89
Datum get_constval() const
Definition: Analyzer.h:348
Definition: sqltypes.h:68
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::vector< llvm::Value * > codegenGeoConstant(const Analyzer::GeoConstant *, const CompilationOptions &)
Definition: GeoIR.cpp:111
Definition: sqltypes.h:72
double doubleval
Definition: Datum.h:78
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::InValues expr,
const CompilationOptions co 
)
private

Definition at line 23 of file InValuesIR.cpp.

References CgenState::addInValuesBitmap(), AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), InValuesBitmap::codegen(), codegenCmp(), CgenState::context_, createInValuesBitmap(), CgenState::emitCall(), executor(), Analyzer::InValues::get_arg(), Analyzer::Expr::get_type_info(), Analyzer::InValues::get_value_list(), CompilationOptions::hoist_literals, CgenState::inlineIntNull(), CgenState::ir_builder_, is_unnest(), kBOOLEAN, kEQ, kONE, CgenState::llInt(), run_benchmark_import::result, and toBool().

24  {
26  const auto in_arg = expr->get_arg();
27  if (is_unnest(in_arg)) {
28  throw std::runtime_error("IN not supported for unnested expressions");
29  }
30  const auto& expr_ti = expr->get_type_info();
31  CHECK(expr_ti.is_boolean());
32  const auto lhs_lvs = codegen(in_arg, true, co);
33  llvm::Value* result{nullptr};
34  if (expr_ti.get_notnull()) {
35  result = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(cgen_state_->context_),
36  false);
37  } else {
38  result = cgen_state_->llInt(int8_t(0));
39  }
40  CHECK(result);
41  if (co.hoist_literals) { // TODO(alex): remove this constraint
42  auto in_vals_bitmap = createInValuesBitmap(expr, co);
43  if (in_vals_bitmap) {
44  if (in_vals_bitmap->isEmpty()) {
45  return in_vals_bitmap->hasNull()
47  : result;
48  }
49  CHECK_EQ(size_t(1), lhs_lvs.size());
50  return cgen_state_->addInValuesBitmap(in_vals_bitmap)
51  ->codegen(lhs_lvs.front(), executor());
52  }
53  }
54  if (expr_ti.get_notnull()) {
55  for (auto in_val : expr->get_value_list()) {
56  result = cgen_state_->ir_builder_.CreateOr(
57  result,
58  toBool(
59  codegenCmp(kEQ, kONE, lhs_lvs, in_arg->get_type_info(), in_val.get(), co)));
60  }
61  } else {
62  for (auto in_val : expr->get_value_list()) {
63  const auto crt =
64  codegenCmp(kEQ, kONE, lhs_lvs, in_arg->get_type_info(), in_val.get(), co);
65  result = cgen_state_->emitCall("logical_or",
66  {result, crt, cgen_state_->inlineIntNull(expr_ti)});
67  }
68  }
69  return result;
70 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:32
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
const InValuesBitmap * addInValuesBitmap(std::unique_ptr< InValuesBitmap > &in_values_bitmap)
Definition: CgenState.h:211
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqldefs.h:74
llvm::Value * codegen(llvm::Value *needle, Executor *executor) const
const std::list< std::shared_ptr< Analyzer::Expr > > & get_value_list() const
Definition: Analyzer.h:646
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:230
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
std::unique_ptr< InValuesBitmap > createInValuesBitmap(const Analyzer::InValues *, const CompilationOptions &)
Definition: InValuesIR.cpp:112
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1677
const Expr * get_arg() const
Definition: Analyzer.h:644
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::InIntegerSet expr,
const CompilationOptions co 
)
private

Definition at line 72 of file InValuesIR.cpp.

References CgenState::addInValuesBitmap(), AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), InValuesBitmap::codegen(), CgenState::context_, Data_Namespace::CPU_LEVEL, CompilationOptions::device_type, executor(), Analyzer::InIntegerSet::get_arg(), Analyzer::Expr::get_type_info(), Analyzer::InIntegerSet::get_value_list(), GPU, Data_Namespace::GPU_LEVEL, CompilationOptions::hoist_literals, inline_int_null_val(), is_unnest(), CgenState::llInt(), and run_benchmark_import::result.

73  {
75  const auto in_arg = in_integer_set->get_arg();
76  if (is_unnest(in_arg)) {
77  throw std::runtime_error("IN not supported for unnested expressions");
78  }
79  const auto& ti = in_integer_set->get_arg()->get_type_info();
80  const auto needle_null_val = inline_int_null_val(ti);
81  if (!co.hoist_literals) {
82  // We never run without literal hoisting in real world scenarios, this avoids a crash
83  // when testing.
84  throw std::runtime_error(
85  "IN subquery with many right-hand side values not supported when literal "
86  "hoisting is disabled");
87  }
88  auto in_vals_bitmap = std::make_unique<InValuesBitmap>(
89  in_integer_set->get_value_list(),
90  needle_null_val,
93  executor()->deviceCount(co.device_type),
94  executor()->data_mgr_,
95  co);
96  const auto& in_integer_set_ti = in_integer_set->get_type_info();
97  CHECK(in_integer_set_ti.is_boolean());
98  const auto lhs_lvs = codegen(in_arg, true, co);
99  llvm::Value* result{nullptr};
100  if (in_integer_set_ti.get_notnull()) {
101  result = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(cgen_state_->context_),
102  false);
103  } else {
104  result = cgen_state_->llInt(int8_t(0));
105  }
106  CHECK(result);
107  CHECK_EQ(size_t(1), lhs_lvs.size());
108  return cgen_state_->addInValuesBitmap(in_vals_bitmap)
109  ->codegen(lhs_lvs.front(), executor());
110 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::LLVMContext & context_
Definition: CgenState.h:382
const InValuesBitmap * addInValuesBitmap(std::unique_ptr< InValuesBitmap > &in_values_bitmap)
Definition: CgenState.h:211
#define AUTOMATIC_IR_METADATA(CGENSTATE)
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::Value * codegen(llvm::Value *needle, Executor *executor) const
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1677
Executor * executor() const

+ Here is the call graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegen ( const Analyzer::CaseExpr case_expr,
const CompilationOptions co 
)
private

Definition at line 20 of file CaseIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegenCase(), CgenState::context_, createStringViewStructType(), get_bit_width(), Analyzer::CaseExpr::get_else_expr(), get_int_type(), Analyzer::Expr::get_type_info(), CgenState::ir_builder_, kENCODING_DICT, and kFLOAT.

21  {
23  const auto case_ti = case_expr->get_type_info();
24  llvm::Type* case_llvm_type = nullptr;
25  bool is_real_str = false;
26  if (case_ti.is_integer() || case_ti.is_time() || case_ti.is_decimal()) {
27  case_llvm_type = get_int_type(get_bit_width(case_ti), cgen_state_->context_);
28  } else if (case_ti.is_fp()) {
29  case_llvm_type = case_ti.get_type() == kFLOAT
30  ? llvm::Type::getFloatTy(cgen_state_->context_)
31  : llvm::Type::getDoubleTy(cgen_state_->context_);
32  } else if (case_ti.is_string()) {
33  if (case_ti.get_compression() == kENCODING_DICT) {
34  case_llvm_type =
35  get_int_type(8 * case_ti.get_logical_size(), cgen_state_->context_);
36  } else {
37  is_real_str = true;
38  case_llvm_type = createStringViewStructType();
39  }
40  } else if (case_ti.is_boolean()) {
41  case_llvm_type = get_int_type(8 * case_ti.get_logical_size(), cgen_state_->context_);
42  } else if (case_ti.is_geometry()) {
43  throw std::runtime_error(
44  "Geospatial column projections are currently not supported in conditional "
45  "expressions.");
46  } else if (case_ti.is_array()) {
47  throw std::runtime_error(
48  "Array column projections are currently not supported in conditional "
49  "expressions.");
50  }
51  CHECK(case_llvm_type);
52  const auto& else_ti = case_expr->get_else_expr()->get_type_info();
53  CHECK_EQ(else_ti.get_type(), case_ti.get_type());
54  llvm::Value* case_val = codegenCase(case_expr, case_llvm_type, is_real_str, co);
55  std::vector<llvm::Value*> ret_vals{case_val};
56  if (is_real_str) {
57  ret_vals.push_back(cgen_state_->ir_builder_.CreateExtractValue(case_val, 0));
58  ret_vals.push_back(cgen_state_->ir_builder_.CreateExtractValue(case_val, 1));
59  ret_vals.back() = cgen_state_->ir_builder_.CreateTrunc(
60  ret_vals.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
61  }
62  return ret_vals;
63 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Expr * get_else_expr() const
Definition: Analyzer.h:1387
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::StructType * createStringViewStructType()
llvm::Value * codegenCase(const Analyzer::CaseExpr *, llvm::Type *case_llvm_type, const bool is_real_str, const CompilationOptions &)
Definition: CaseIR.cpp:65
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::ExtractExpr extract_expr,
const CompilationOptions co 
)
private

Definition at line 76 of file DateTimeIR.cpp.

References AUTOMATIC_IR_METADATA, CHECK, DateTimeUtils::get_extract_timestamp_precision_scale(), Analyzer::ExtractExpr::get_field(), Analyzer::ExtractExpr::get_from_expr(), get_int_type(), Analyzer::Expr::get_type_info(), DateTimeUtils::is_subsecond_extract_field(), kDATE, kEPOCH, and kTIMESTAMP.

77  {
79  auto from_expr = codegen(extract_expr->get_from_expr(), true, co).front();
80  const int32_t extract_field{extract_expr->get_field()};
81  const auto& extract_expr_ti = extract_expr->get_from_expr()->get_type_info();
82  if (extract_field == kEPOCH) {
83  CHECK(extract_expr_ti.get_type() == kTIMESTAMP ||
84  extract_expr_ti.get_type() == kDATE);
85  if (from_expr->getType()->isIntegerTy(32)) {
86  from_expr =
87  cgen_state_->ir_builder_.CreateCast(llvm::Instruction::CastOps::SExt,
88  from_expr,
90  return from_expr;
91  }
92  }
93  CHECK(from_expr->getType()->isIntegerTy(64));
94  if (extract_expr_ti.is_high_precision_timestamp()) {
96  from_expr, extract_expr_ti, extract_expr->get_field());
97  }
98  if (!extract_expr_ti.is_high_precision_timestamp() &&
99  is_subsecond_extract_field(extract_expr->get_field())) {
100  from_expr =
101  extract_expr_ti.get_notnull()
102  ? cgen_state_->ir_builder_.CreateMul(
103  from_expr,
107  "mul_int64_t_nullable_lhs",
108  {from_expr,
111  cgen_state_->inlineIntNull(extract_expr_ti)});
112  }
113  const auto extract_fname = get_extract_function_name(extract_expr->get_field());
114  if (!extract_expr_ti.get_notnull()) {
115  llvm::BasicBlock* extract_nullcheck_bb{nullptr};
116  llvm::PHINode* extract_nullcheck_value{nullptr};
117  {
118  DiamondCodegen null_check(cgen_state_->ir_builder_.CreateICmp(
119  llvm::ICmpInst::ICMP_EQ,
120  from_expr,
121  cgen_state_->inlineIntNull(extract_expr_ti)),
122  executor(),
123  false,
124  "extract_nullcheck",
125  nullptr,
126  false);
127  // generate a phi node depending on whether we got a null or not
128  extract_nullcheck_bb = llvm::BasicBlock::Create(
129  cgen_state_->context_, "extract_nullcheck_bb", cgen_state_->current_func_);
130 
131  // update the blocks created by diamond codegen to point to the newly created phi
132  // block
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_);
136  auto extract_call =
137  cgen_state_->emitExternalCall(extract_fname,
139  std::vector<llvm::Value*>{from_expr});
140  cgen_state_->ir_builder_.CreateBr(extract_nullcheck_bb);
141 
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_);
148  }
149 
150  // diamond codegen will set the insert point in its destructor. override it to
151  // continue using the extract nullcheck bb
152  CHECK(extract_nullcheck_bb);
153  cgen_state_->ir_builder_.SetInsertPoint(extract_nullcheck_bb);
154  CHECK(extract_nullcheck_value);
155  return extract_nullcheck_value;
156  } else {
157  return cgen_state_->emitExternalCall(extract_fname,
159  std::vector<llvm::Value*>{from_expr});
160  }
161 }
const Expr * get_from_expr() const
Definition: Analyzer.h:1432
constexpr int64_t get_extract_timestamp_precision_scale(const ExtractField field)
Definition: DateTimeUtils.h:81
CgenState * cgen_state_
ExtractField get_field() const
Definition: Analyzer.h:1431
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
const char * get_extract_function_name(ExtractField field)
Definition: DateTimeIR.cpp:26
llvm::Value * codegenExtractHighPrecisionTimestamps(llvm::Value *, const SQLTypeInfo &, const ExtractField &)
Definition: DateTimeIR.cpp:260
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqltypes.h:80
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
constexpr bool is_subsecond_extract_field(const ExtractField &field)
Definition: DateTimeUtils.h:95
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::DateaddExpr dateadd_expr,
const CompilationOptions co 
)
private

Definition at line 163 of file DateTimeIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), CgenState::context_, CgenState::emitExternalCall(), Analyzer::DateaddExpr::get_datetime_expr(), Analyzer::DateaddExpr::get_field(), get_int_type(), Analyzer::DateaddExpr::get_number_expr(), Analyzer::Expr::get_type_info(), inline_fixed_encoding_null_val(), inline_int_null_val(), DateTimeUtils::is_subsecond_dateadd_field(), kDATE, kTIMESTAMP, CgenState::llInt(), and Analyzer::DateaddExpr::use_fixed_encoding_null_val().

164  {
166  const auto& dateadd_expr_ti = dateadd_expr->get_type_info();
167  CHECK(dateadd_expr_ti.get_type() == kTIMESTAMP || dateadd_expr_ti.get_type() == kDATE);
168  auto datetime = codegen(dateadd_expr->get_datetime_expr(), true, co).front();
169  CHECK(datetime->getType()->isIntegerTy(64));
170  auto number = codegen(dateadd_expr->get_number_expr(), true, co).front();
171 
172  const auto& datetime_ti = dateadd_expr->get_datetime_expr()->get_type_info();
173  std::vector<llvm::Value*> dateadd_args{
174  cgen_state_->llInt(static_cast<int32_t>(dateadd_expr->get_field())),
175  number,
176  datetime};
177  std::string dateadd_fname{"DateAdd"};
178  if (is_subsecond_dateadd_field(dateadd_expr->get_field()) ||
179  dateadd_expr_ti.is_high_precision_timestamp()) {
180  dateadd_fname += "HighPrecision";
181  dateadd_args.push_back(
182  cgen_state_->llInt(static_cast<int32_t>(datetime_ti.get_dimension())));
183  }
184  if (!datetime_ti.get_notnull()) {
185  auto null_val = dateadd_expr->use_fixed_encoding_null_val()
186  ? inline_fixed_encoding_null_val(datetime_ti)
187  : inline_int_null_val(datetime_ti);
188  dateadd_args.push_back(cgen_state_->llInt((int64_t)null_val));
189  dateadd_fname += "Nullable";
190  }
191  return cgen_state_->emitExternalCall(dateadd_fname,
193  dateadd_args,
194  {llvm::Attribute::NoUnwind,
195  llvm::Attribute::ReadNone,
196  llvm::Attribute::Speculatable});
197 }
CgenState * cgen_state_
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqltypes.h:80
const Expr * get_datetime_expr() const
Definition: Analyzer.h:1478
DateaddField get_field() const
Definition: Analyzer.h:1476
constexpr bool is_subsecond_dateadd_field(const DateaddField field)
Definition: DateTimeUtils.h:99
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
int64_t inline_fixed_encoding_null_val(const SQL_TYPE_INFO &ti)
bool use_fixed_encoding_null_val() const
Definition: Analyzer.h:1480
const Expr * get_number_expr() const
Definition: Analyzer.h:1477

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::DatediffExpr datediff_expr,
const CompilationOptions co 
)
private

Definition at line 199 of file DateTimeIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), CgenState::context_, CgenState::emitExternalCall(), Analyzer::DatediffExpr::get_end_expr(), Analyzer::DatediffExpr::get_field(), get_int_type(), Analyzer::DatediffExpr::get_start_expr(), Analyzer::Expr::get_type_info(), CgenState::inlineIntNull(), and CgenState::llInt().

200  {
202  auto start = codegen(datediff_expr->get_start_expr(), true, co).front();
203  CHECK(start->getType()->isIntegerTy(64));
204  auto end = codegen(datediff_expr->get_end_expr(), true, co).front();
205  CHECK(end->getType()->isIntegerTy(32) || end->getType()->isIntegerTy(64));
206  const auto& start_ti = datediff_expr->get_start_expr()->get_type_info();
207  const auto& end_ti = datediff_expr->get_end_expr()->get_type_info();
208  std::vector<llvm::Value*> datediff_args{
209  cgen_state_->llInt(static_cast<int32_t>(datediff_expr->get_field())), start, end};
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(
214  cgen_state_->llInt(static_cast<int32_t>(start_ti.get_dimension())));
215  datediff_args.push_back(
216  cgen_state_->llInt(static_cast<int32_t>(end_ti.get_dimension())));
217  }
218  const auto& ret_ti = datediff_expr->get_type_info();
219  if (!start_ti.get_notnull() || !end_ti.get_notnull()) {
220  datediff_args.push_back(cgen_state_->inlineIntNull(ret_ti));
221  datediff_fname += "Nullable";
222  }
224  datediff_fname, get_int_type(64, cgen_state_->context_), datediff_args);
225 }
CgenState * cgen_state_
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const Expr * get_start_expr() const
Definition: Analyzer.h:1525
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
const Expr * get_end_expr() const
Definition: Analyzer.h:1526
#define CHECK(condition)
Definition: Logger.h:291
DatetruncField get_field() const
Definition: Analyzer.h:1524

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::DatetruncExpr datetrunc_expr,
const CompilationOptions co 
)
private

Definition at line 227 of file DateTimeIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), codegenDateTruncHighPrecisionTimestamps(), CgenState::context_, datetrunc_fname_lookup, dtMICROSECOND, dtMILLISECOND, dtNANOSECOND, dtSECOND, CgenState::emitExternalCall(), executor(), field(), Analyzer::DatetruncExpr::get_field(), Analyzer::DatetruncExpr::get_from_expr(), get_int_type(), Analyzer::Expr::get_type_info(), and CgenState::ir_builder_.

228  {
230  auto from_expr = codegen(datetrunc_expr->get_from_expr(), true, co).front();
231  const auto& datetrunc_expr_ti = datetrunc_expr->get_from_expr()->get_type_info();
232  CHECK(from_expr->getType()->isIntegerTy(64));
233  DatetruncField const field = datetrunc_expr->get_field();
234  if (datetrunc_expr_ti.is_high_precision_timestamp()) {
235  return codegenDateTruncHighPrecisionTimestamps(from_expr, datetrunc_expr_ti, field);
236  }
237  static_assert(dtSECOND + 1 == dtMILLISECOND, "Please keep these consecutive.");
238  static_assert(dtMILLISECOND + 1 == dtMICROSECOND, "Please keep these consecutive.");
239  static_assert(dtMICROSECOND + 1 == dtNANOSECOND, "Please keep these consecutive.");
240  if (dtSECOND <= field && field <= dtNANOSECOND) {
241  return cgen_state_->ir_builder_.CreateCast(llvm::Instruction::CastOps::SExt,
242  from_expr,
244  }
245  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
246  const bool is_nullable = !datetrunc_expr_ti.get_notnull();
247  if (is_nullable) {
248  nullcheck_codegen = std::make_unique<NullCheckCodegen>(
249  cgen_state_, executor(), from_expr, datetrunc_expr_ti, "date_trunc_nullcheck");
250  }
251  char const* const fname = datetrunc_fname_lookup.at(field);
252  auto ret = cgen_state_->emitExternalCall(
253  fname, get_int_type(64, cgen_state_->context_), {from_expr});
254  if (is_nullable) {
255  ret = nullcheck_codegen->finalize(ll_int(NULL_BIGINT, cgen_state_->context_), ret);
256  }
257  return ret;
258 }
CgenState * cgen_state_
#define NULL_BIGINT
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
DatetruncField get_field() const
Definition: Analyzer.h:1566
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
DatetruncField
Definition: DateTruncate.h:27
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
constexpr std::array< char const *, dtINVALID > datetrunc_fname_lookup
Definition: DateTruncate.h:49
const Expr * get_from_expr() const
Definition: Analyzer.h:1567
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * codegenDateTruncHighPrecisionTimestamps(llvm::Value *, const SQLTypeInfo &, const DatetruncField &)
Definition: DateTimeIR.cpp:304
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::CharLengthExpr expr,
const CompilationOptions co 
)
private

Definition at line 239 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, codegen(), CgenState::context_, CompilationOptions::device_type, CgenState::emitCall(), CgenState::emitExternalCall(), Analyzer::CharLengthExpr::get_arg(), Analyzer::CharLengthExpr::get_calc_encoded_length(), get_int_type(), SQLTypeInfo::get_notnull(), Analyzer::Expr::get_type_info(), GPU, CgenState::inlineIntNull(), and CgenState::ir_builder_.

240  {
242  auto str_lv = codegen(expr->get_arg(), true, co);
243  if (str_lv.size() != 3) {
244  CHECK_EQ(size_t(1), str_lv.size());
245  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 0));
246  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 1));
247  str_lv.back() = cgen_state_->ir_builder_.CreateTrunc(
248  str_lv.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
250  throw QueryMustRunOnCpu();
251  }
252  }
253  std::vector<llvm::Value*> charlength_args{str_lv[1], str_lv[2]};
254  std::string fn_name("char_length");
255  if (expr->get_calc_encoded_length()) {
256  fn_name += "_encoded";
257  }
258  const bool is_nullable{!expr->get_arg()->get_type_info().get_notnull()};
259  if (is_nullable) {
260  fn_name += "_nullable";
261  charlength_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
262  }
263  return expr->get_calc_encoded_length()
265  fn_name, get_int_type(32, cgen_state_->context_), charlength_args)
266  : cgen_state_->emitCall(fn_name, charlength_args);
267 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool get_calc_encoded_length() const
Definition: Analyzer.h:870
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_arg() const
Definition: Analyzer.h:868
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::KeyForStringExpr expr,
const CompilationOptions co 
)
private

Definition at line 269 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, codegen(), CgenState::emitCall(), and Analyzer::KeyForStringExpr::get_arg().

270  {
272  auto str_lv = codegen(expr->get_arg(), true, co);
273  CHECK_EQ(size_t(1), str_lv.size());
274  return cgen_state_->emitCall("key_for_string_encoded", str_lv);
275 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_arg() const
Definition: Analyzer.h:917

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::SampleRatioExpr expr,
const CompilationOptions co 
)
private

Definition at line 278 of file IRCodegen.cpp.

References run_benchmark_import::args, AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), CgenState::context_, CgenState::emitCall(), executor(), Analyzer::SampleRatioExpr::get_arg(), kDOUBLE, ll_bool(), and posArg().

279  {
281  auto input_expr = expr->get_arg();
282  CHECK(input_expr);
283 
284  auto double_lv = codegen(input_expr, true, co);
285  CHECK_EQ(size_t(1), double_lv.size());
286 
287  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
288  const bool is_nullable = !input_expr->get_type_info().get_notnull();
289  if (is_nullable) {
290  nullcheck_codegen = std::make_unique<NullCheckCodegen>(cgen_state_,
291  executor(),
292  double_lv.front(),
293  input_expr->get_type_info(),
294  "sample_ratio_nullcheck");
295  }
296  CHECK_EQ(input_expr->get_type_info().get_type(), kDOUBLE);
297  std::vector<llvm::Value*> args{double_lv[0], posArg(nullptr)};
298  auto ret = cgen_state_->emitCall("sample_ratio", args);
299  if (nullcheck_codegen) {
300  ret = nullcheck_codegen->finalize(ll_bool(false, cgen_state_->context_), ret);
301  }
302  return ret;
303 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_arg() const
Definition: Analyzer.h:962
#define CHECK(condition)
Definition: Logger.h:291
llvm::ConstantInt * ll_bool(const bool v, llvm::LLVMContext &context)
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::WidthBucketExpr expr,
const CompilationOptions co 
)
private

Definition at line 305 of file IRCodegen.cpp.

References AUTOMATIC_IR_METADATA, Analyzer::WidthBucketExpr::can_skip_out_of_bound_check(), cgen_state_, CHECK, codegenConstantWidthBucketExpr(), codegenWidthBucketExpr(), executor_, Analyzer::WidthBucketExpr::get_lower_bound(), Analyzer::WidthBucketExpr::get_partition_count(), Analyzer::WidthBucketExpr::get_partition_count_val(), Analyzer::WidthBucketExpr::get_target_value(), Analyzer::WidthBucketExpr::get_upper_bound(), getExpressionRange(), PlanState::getSimpleQuals(), Integer, Analyzer::WidthBucketExpr::is_constant_expr(), kCAST, plan_state_, PlanState::query_infos_, Analyzer::WidthBucketExpr::set_constant_expr(), and Analyzer::WidthBucketExpr::skip_out_of_bound_check().

306  {
308  auto target_value_expr = expr->get_target_value();
309  auto lower_bound_expr = expr->get_lower_bound();
310  auto upper_bound_expr = expr->get_upper_bound();
311  auto partition_count_expr = expr->get_partition_count();
312  CHECK(target_value_expr);
313  CHECK(lower_bound_expr);
314  CHECK(upper_bound_expr);
315  CHECK(partition_count_expr);
316 
317  auto is_constant_expr = [](const Analyzer::Expr* expr) {
318  auto target_expr = expr;
319  if (auto cast_expr = dynamic_cast<const Analyzer::UOper*>(expr)) {
320  if (cast_expr->get_optype() == SQLOps::kCAST) {
321  target_expr = cast_expr->get_operand();
322  }
323  }
324  // there are more complex constant expr like 1+2, 1/2*3, and so on
325  // but when considering a typical usage of width_bucket function
326  // it is sufficient to consider a singleton constant expr
327  auto constant_expr = dynamic_cast<const Analyzer::Constant*>(target_expr);
328  if (constant_expr) {
329  return true;
330  }
331  return false;
332  };
333  if (is_constant_expr(lower_bound_expr) && is_constant_expr(upper_bound_expr) &&
334  is_constant_expr(partition_count_expr)) {
335  expr->set_constant_expr();
336  }
337  // compute width_bucket's expresn range and check the possibility of avoiding oob check
338  auto col_range =
339  getExpressionRange(expr,
341  executor_,
342  boost::make_optional(plan_state_->getSimpleQuals()));
343  // check whether target_expr is valid
344  if (col_range.getType() == ExpressionRangeType::Integer &&
345  !expr->can_skip_out_of_bound_check() && col_range.getIntMin() > 0 &&
346  col_range.getIntMax() <= expr->get_partition_count_val()) {
347  // check whether target_col is not-nullable or has filter expr on it
348  if (!col_range.hasNulls()) {
349  // Even if the target_expr has its filter expression, target_col_range may exactly
350  // the same with the col_range of the target_expr's operand col,
351  // i.e., SELECT WIDTH_BUCKET(v1, 1, 10, 10) FROM T WHERE v1 != 1;
352  // In that query, col_range of v1 with/without considering the filter expression
353  // v1 != 1 have exactly the same col ranges, so we cannot recognize the existence
354  // of the filter expression based on them. Also, is (not) null is located in
355  // FilterNode, so we cannot trace it in here.
356  // todo (yoonmin): relax this to allow skipping oob check more cases
357  expr->skip_out_of_bound_check();
358  }
359  }
360  return expr->is_constant_expr() ? codegenConstantWidthBucketExpr(expr, co)
361  : codegenWidthBucketExpr(expr, co);
362 }
const Expr * get_partition_count() const
Definition: Analyzer.h:1201
bool is_constant_expr() const
Definition: Analyzer.h:1246
llvm::Value * codegenConstantWidthBucketExpr(const Analyzer::WidthBucketExpr *, const CompilationOptions &)
Definition: IRCodegen.cpp:364
CgenState * cgen_state_
Definition: sqldefs.h:51
void set_constant_expr() const
Definition: Analyzer.h:1245
llvm::Value * codegenWidthBucketExpr(const Analyzer::WidthBucketExpr *, const CompilationOptions &)
Definition: IRCodegen.cpp:437
Executor * executor_
const std::vector< InputTableInfo > & query_infos_
Definition: PlanState.h:65
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)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
PlanState * plan_state_
int32_t get_partition_count_val() const
Definition: Analyzer.cpp:3946
std::list< std::shared_ptr< Analyzer::Expr > > getSimpleQuals() const
Definition: PlanState.h:97
const Expr * get_target_value() const
Definition: Analyzer.h:1198
#define CHECK(condition)
Definition: Logger.h:291
bool can_skip_out_of_bound_check() const
Definition: Analyzer.h:1243
void skip_out_of_bound_check() const
Definition: Analyzer.h:1244
const Expr * get_lower_bound() const
Definition: Analyzer.h:1199
const Expr * get_upper_bound() const
Definition: Analyzer.h:1200

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::MLPredictExpr expr,
const CompilationOptions co 
)
private

Definition at line 288 of file MLPredictCodegen.cpp.

References CHECK, codegenLinRegPredict(), codegenTreeRegPredict(), DEBUG_TIMER, DECISION_TREE_REG, g_ml_models, GBT_REG, Analyzer::MLPredictExpr::get_model_value(), Analyzer::MLPredictExpr::get_regressor_values(), MLModelMap::getModel(), LINEAR_REG, and RANDOM_FOREST_REG.

289  {
290  auto timer = DEBUG_TIMER(__func__);
291  const auto& model_expr = expr->get_model_value();
292  CHECK(model_expr);
293  auto model_constant_expr = dynamic_cast<const Analyzer::Constant*>(model_expr);
294  CHECK(model_constant_expr);
295  const auto model_datum = model_constant_expr->get_constval();
296  const auto model_name_ptr = model_datum.stringval;
297  CHECK(model_name_ptr);
298  const auto model_name = *model_name_ptr;
299  const auto abstract_model = g_ml_models.getModel(model_name);
300  const auto model_type = abstract_model->getModelType();
301  const auto& regressor_exprs = expr->get_regressor_values();
302  if (abstract_model->getNumLogicalFeatures() !=
303  static_cast<int64_t>(regressor_exprs.size())) {
304  std::ostringstream error_oss;
305  error_oss << "ML_PREDICT: Model '" << model_name
306  << "' expects different number of predictor variables ("
307  << abstract_model->getNumLogicalFeatures() << ") than provided ("
308  << regressor_exprs.size() << ").";
309  throw std::runtime_error(error_oss.str());
310  }
311 
312  switch (model_type) {
314  return codegenLinRegPredict(expr, abstract_model, co);
315  }
319  if (auto tree_model =
320  std::dynamic_pointer_cast<AbstractTreeModel>(abstract_model)) {
321  return codegenTreeRegPredict(expr, tree_model, co);
322  } else {
323  throw std::runtime_error(
324  "Invalid ML model codegen call. Input model is not of expected type "
325  "TreeModel.");
326  }
327  }
328  default: {
329  throw std::runtime_error("Unsupported model type.");
330  }
331  }
332 }
llvm::Value * codegenTreeRegPredict(const Analyzer::MLPredictExpr *, const std::shared_ptr< AbstractTreeModel > &tree_model, const CompilationOptions &)
llvm::Value * codegenLinRegPredict(const Analyzer::MLPredictExpr *, const std::shared_ptr< AbstractMLModel > &model, const CompilationOptions &)
std::shared_ptr< AbstractMLModel > getModel(const std::string &model_name) const
Definition: MLModel.h:51
MLModelMap g_ml_models
Definition: MLModel.h:125
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412
const Expr * get_model_value() const
Definition: Analyzer.h:713
const std::vector< std::shared_ptr< Analyzer::Expr > > & get_regressor_values() const
Definition: Analyzer.h:714

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::PCAProjectExpr expr,
const CompilationOptions co 
)
private

Definition at line 334 of file MLPredictCodegen.cpp.

References CHECK, codegenArith(), DEBUG_TIMER, Datum::doubleval, executor(), g_ml_models, generated_encoded_and_casted_features(), Analyzer::Constant::get_constval(), Analyzer::PCAProjectExpr::get_feature_values(), Analyzer::PCAProjectExpr::get_model_value(), Analyzer::PCAProjectExpr::get_pc_dimension_value(), MLModelMap::getModel(), Datum::intval, kDIVIDE, kDOUBLE, kMINUS, kMULTIPLY, kONE, kPLUS, PCA, and run_benchmark_import::result.

335  {
336  auto timer = DEBUG_TIMER(__func__);
337  const auto& model_expr = expr->get_model_value();
338  CHECK(model_expr);
339  auto model_constant_expr = dynamic_cast<const Analyzer::Constant*>(model_expr);
340  CHECK(model_constant_expr);
341  const auto model_datum = model_constant_expr->get_constval();
342  const auto model_name_ptr = model_datum.stringval;
343  CHECK(model_name_ptr);
344  const auto model_name = *model_name_ptr;
345  const auto abstract_model = g_ml_models.getModel(model_name);
346  const auto model_type = abstract_model->getModelType();
347  if (model_type != MLModelType::PCA) {
348  throw std::runtime_error("PCA_PROJECT: Model '" + model_name +
349  "' is not a PCA model.");
350  }
351  const auto pca_model = std::dynamic_pointer_cast<PcaModel>(abstract_model);
352  const auto& feature_exprs = expr->get_feature_values();
353  if (pca_model->getNumLogicalFeatures() != static_cast<int64_t>(feature_exprs.size())) {
354  std::ostringstream error_oss;
355  error_oss << "PCA_PROJECT: Model '" << model_name
356  << "' expects different number of predictor variables ("
357  << pca_model->getNumLogicalFeatures() << ") than provided ("
358  << feature_exprs.size() << ").";
359  throw std::runtime_error(error_oss.str());
360  }
361 
362  const auto& pc_dimension_expr = expr->get_pc_dimension_value();
363  auto pc_dimension_const_expr =
364  dynamic_cast<const Analyzer::Constant*>(pc_dimension_expr);
365  const auto pc_dimension_datum = pc_dimension_const_expr->get_constval();
366  const auto pc_dimension = pc_dimension_datum.intval - 1;
367  if (pc_dimension < 0 || pc_dimension >= pca_model->getNumFeatures()) {
368  std::ostringstream error_oss;
369  error_oss << "PCA_PROJECT: Invalid PC dimension (" << pc_dimension + 1
370  << ") provided. Valid range is [1, " << pca_model->getNumFeatures() << "].";
371  throw std::runtime_error(error_oss.str());
372  }
373 
374  const auto& column_means = pca_model->getColumnMeans();
375  const auto& column_std_devs = pca_model->getColumnStdDevs();
376  const auto& eigenvectors = pca_model->getEigenvectors();
377 
378  const auto& cat_feature_keys = pca_model->getCatFeatureKeys();
379 
380  const auto casted_feature_exprs = generated_encoded_and_casted_features(
381  feature_exprs,
382  cat_feature_keys,
383  pca_model->getModelMetadata().getFeaturePermutations(),
384  executor());
385 
386  auto get_double_constant_expr = [](double const_val) {
387  Datum d;
388  d.doubleval = const_val;
389  return makeExpr<Analyzer::Constant>(SQLTypeInfo(kDOUBLE, false), false, d);
390  };
391 
392  std::shared_ptr<Analyzer::Expr> result;
393 
394  for (size_t feature_idx = 0; feature_idx < feature_exprs.size(); ++feature_idx) {
395  auto mean_expr = get_double_constant_expr(column_means[feature_idx]);
396  const auto& casted_feature_expr = casted_feature_exprs[feature_idx];
397  // Subtract column mean from feature
398  auto mean_diff_expr = makeExpr<Analyzer::BinOper>(
399  SQLTypeInfo(kDOUBLE, false), false, kMINUS, kONE, casted_feature_expr, mean_expr);
400  auto std_dev_expr = get_double_constant_expr(column_std_devs[feature_idx]);
401  auto z_score_expr = makeExpr<Analyzer::BinOper>(
402  SQLTypeInfo(kDOUBLE, false), false, kDIVIDE, kONE, mean_diff_expr, std_dev_expr);
403  auto pc_term_expr = get_double_constant_expr(eigenvectors[pc_dimension][feature_idx]);
404  auto pca_mul_expr = makeExpr<Analyzer::BinOper>(
405  SQLTypeInfo(kDOUBLE, false), false, kMULTIPLY, kONE, z_score_expr, pc_term_expr);
406  if (feature_idx == 0) {
407  // There is no result yet, so set the result to the first term
408  result = pca_mul_expr;
409  } else {
410  // Add the term to the result
411  result = makeExpr<Analyzer::BinOper>(
412  SQLTypeInfo(kDOUBLE, false), false, kPLUS, kONE, result, pca_mul_expr);
413  }
414  }
415 
416  // The following will codegen the expression tree we just created modeling
417  // the linear regression formula
418  return codegenArith(dynamic_cast<Analyzer::BinOper*>(result.get()), co);
419 }
llvm::Value * codegenArith(const Analyzer::BinOper *, const CompilationOptions &)
Definition: sqldefs.h:43
int32_t intval
Definition: Datum.h:75
std::vector< std::shared_ptr< Analyzer::Expr > > generated_encoded_and_casted_features(const std::vector< std::shared_ptr< Analyzer::Expr >> &feature_exprs, const std::vector< std::vector< std::string >> &cat_feature_keys, const std::vector< int64_t > &feature_permutations, Executor *executor)
const Expr * get_pc_dimension_value() const
Definition: Analyzer.h:792
std::shared_ptr< AbstractMLModel > getModel(const std::string &model_name) const
Definition: MLModel.h:51
MLModelMap g_ml_models
Definition: MLModel.h:125
Definition: sqldefs.h:42
Definition: sqldefs.h:74
Datum get_constval() const
Definition: Analyzer.h:348
const Expr * get_model_value() const
Definition: Analyzer.h:788
const std::vector< std::shared_ptr< Analyzer::Expr > > & get_feature_values() const
Definition: Analyzer.h:789
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412
Definition: Datum.h:71
double doubleval
Definition: Datum.h:78
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::StringOper expr,
const CompilationOptions co 
)
private

Definition at line 533 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, CHECK_GE, codegen(), StringDictionaryTranslationMgr::codegen(), codegenPerRowStringOper(), CompilationOptions::device_type, executor(), Analyzer::Expr::get_type_info(), Analyzer::StringOper::getArg(), Analyzer::StringOper::getArity(), CgenState::moveStringDictionaryTranslationMgr(), Analyzer::StringOper::requiresPerRowTranslation(), and translate_dict_strings().

534  {
535  CHECK_GE(expr->getArity(), 1UL);
536  if (expr->requiresPerRowTranslation()) {
537  return codegenPerRowStringOper(expr, co);
538  }
539 
541 
542  auto string_dictionary_translation_mgr =
544 
545  auto str_id_lv = codegen(expr->getArg(0), true, co);
546  CHECK_EQ(size_t(1), str_id_lv.size());
547  const auto& expr_ti = expr->get_type_info();
548 
549  return cgen_state_
550  ->moveStringDictionaryTranslationMgr(std::move(string_dictionary_translation_mgr))
551  ->codegen(str_id_lv[0], expr_ti, true /* add_nullcheck */, co);
552 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
llvm::Value * codegenPerRowStringOper(const Analyzer::StringOper *string_oper, const CompilationOptions &co)
CgenState * cgen_state_
std::unique_ptr< StringDictionaryTranslationMgr > translate_dict_strings(const Analyzer::StringOper *expr, const ExecutorDeviceType device_type, Executor *executor)
#define CHECK_GE(x, y)
Definition: Logger.h:306
size_t getArity() const
Definition: Analyzer.h:1674
bool requiresPerRowTranslation() const
Definition: Analyzer.h:1704
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const StringDictionaryTranslationMgr * moveStringDictionaryTranslationMgr(std::unique_ptr< const StringDictionaryTranslationMgr > &&str_dict_translation_mgr)
Definition: CgenState.h:199
llvm::Value * codegen(llvm::Value *str_id_input, const SQLTypeInfo &input_ti, const bool add_nullcheck, const CompilationOptions &co) const
const Expr * getArg(const size_t i) const
Definition: Analyzer.h:1688
Executor * executor() const

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::LikeExpr expr,
const CompilationOptions co 
)
private

Definition at line 587 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), codegenDictLike(), CgenState::context_, CompilationOptions::device_type, CgenState::emitCall(), extract_cast_arg(), g_enable_watchdog, Analyzer::LikeExpr::get_arg(), Analyzer::LikeExpr::get_escape_expr(), Analyzer::LikeExpr::get_is_ilike(), Analyzer::LikeExpr::get_is_simple(), Analyzer::LikeExpr::get_like_expr(), SQLTypeInfo::get_notnull(), Analyzer::LikeExpr::get_own_arg(), Analyzer::Expr::get_type_info(), GPU, CgenState::inlineIntNull(), CgenState::ir_builder_, is_unnest(), kENCODING_NONE, and CgenState::llInt().

588  {
590  if (is_unnest(extract_cast_arg(expr->get_arg()))) {
591  throw std::runtime_error("LIKE not supported for unnested expressions");
592  }
593  char escape_char{'\\'};
594  if (expr->get_escape_expr()) {
595  auto escape_char_expr =
596  dynamic_cast<const Analyzer::Constant*>(expr->get_escape_expr());
597  CHECK(escape_char_expr);
598  CHECK(escape_char_expr->get_type_info().is_string());
599  CHECK_EQ(size_t(1), escape_char_expr->get_constval().stringval->size());
600  escape_char = (*escape_char_expr->get_constval().stringval)[0];
601  }
602  auto pattern = dynamic_cast<const Analyzer::Constant*>(expr->get_like_expr());
603  CHECK(pattern);
604  auto fast_dict_like_lv = codegenDictLike(expr->get_own_arg(),
605  pattern,
606  expr->get_is_ilike(),
607  expr->get_is_simple(),
608  escape_char,
609  co);
610  if (fast_dict_like_lv) {
611  return fast_dict_like_lv;
612  }
613  const auto& ti = expr->get_arg()->get_type_info();
614  CHECK(ti.is_string());
615  if (g_enable_watchdog && ti.get_compression() != kENCODING_NONE) {
616  throw WatchdogException(
617  "Cannot do LIKE / ILIKE on this dictionary encoded column, its cardinality is "
618  "too high");
619  }
620  auto str_lv = codegen(expr->get_arg(), true, co);
621  if (str_lv.size() != 3) {
622  CHECK_EQ(size_t(1), str_lv.size());
623  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 0));
624  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 1));
625  str_lv.back() = cgen_state_->ir_builder_.CreateTrunc(
626  str_lv.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
628  throw QueryMustRunOnCpu();
629  }
630  }
631  auto like_expr_arg_lvs = codegen(expr->get_like_expr(), true, co);
632  CHECK_EQ(size_t(3), like_expr_arg_lvs.size());
633  const bool is_nullable{!expr->get_arg()->get_type_info().get_notnull()};
634  std::vector<llvm::Value*> str_like_args{str_lv[1],
635  str_lv[2],
636  like_expr_arg_lvs[1],
637  like_expr_arg_lvs[2],
638  cgen_state_->llInt(int8_t(escape_char))};
639  std::string fn_name{expr->get_is_ilike() ? "string_ilike" : "string_like"};
640  if (expr->get_is_simple()) {
641  fn_name += "_simple";
642  }
643  if (is_nullable) {
644  fn_name += "_nullable";
645  str_like_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
646  }
647  return cgen_state_->emitCall(fn_name, str_like_args);
648 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Expr * get_escape_expr() const
Definition: Analyzer.h:1064
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
const Analyzer::Expr * extract_cast_arg(const Analyzer::Expr *expr)
Definition: Execute.h:222
const Expr * get_arg() const
Definition: Analyzer.h:1061
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool g_enable_watchdog
bool get_is_simple() const
Definition: Analyzer.h:1066
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_like_expr() const
Definition: Analyzer.h:1063
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
const std::shared_ptr< Analyzer::Expr > get_own_arg() const
Definition: Analyzer.h:1062
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1677
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
bool get_is_ilike() const
Definition: Analyzer.h:1065
llvm::Value * codegenDictLike(const std::shared_ptr< Analyzer::Expr > arg, const Analyzer::Constant *pattern, const bool ilike, const bool is_simple, const char escape_char, const CompilationOptions &)

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::RegexpExpr expr,
const CompilationOptions co 
)
private

Definition at line 845 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), codegenDictRegexp(), CgenState::context_, CompilationOptions::device_type, CgenState::emitExternalCall(), extract_cast_arg(), g_enable_watchdog, Analyzer::RegexpExpr::get_arg(), Analyzer::RegexpExpr::get_escape_expr(), get_int_type(), SQLTypeInfo::get_notnull(), Analyzer::RegexpExpr::get_own_arg(), Analyzer::RegexpExpr::get_pattern_expr(), Analyzer::Expr::get_type_info(), GPU, CgenState::inlineIntNull(), CgenState::ir_builder_, is_unnest(), kENCODING_NONE, and CgenState::llInt().

846  {
848  if (is_unnest(extract_cast_arg(expr->get_arg()))) {
849  throw std::runtime_error("REGEXP not supported for unnested expressions");
850  }
851  char escape_char{'\\'};
852  if (expr->get_escape_expr()) {
853  auto escape_char_expr =
854  dynamic_cast<const Analyzer::Constant*>(expr->get_escape_expr());
855  CHECK(escape_char_expr);
856  CHECK(escape_char_expr->get_type_info().is_string());
857  CHECK_EQ(size_t(1), escape_char_expr->get_constval().stringval->size());
858  escape_char = (*escape_char_expr->get_constval().stringval)[0];
859  }
860  auto pattern = dynamic_cast<const Analyzer::Constant*>(expr->get_pattern_expr());
861  CHECK(pattern);
862  auto fast_dict_pattern_lv =
863  codegenDictRegexp(expr->get_own_arg(), pattern, escape_char, co);
864  if (fast_dict_pattern_lv) {
865  return fast_dict_pattern_lv;
866  }
867  const auto& ti = expr->get_arg()->get_type_info();
868  CHECK(ti.is_string());
869  if (g_enable_watchdog && ti.get_compression() != kENCODING_NONE) {
870  throw WatchdogException(
871  "Cannot do REGEXP_LIKE on this dictionary encoded column, its cardinality is too "
872  "high");
873  }
874  // Now we know we are working on NONE ENCODED column. So switch back to CPU
876  throw QueryMustRunOnCpu();
877  }
878  auto str_lv = codegen(expr->get_arg(), true, co);
879  if (str_lv.size() != 3) {
880  CHECK_EQ(size_t(1), str_lv.size());
881  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 0));
882  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 1));
883  str_lv.back() = cgen_state_->ir_builder_.CreateTrunc(
884  str_lv.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
885  }
886  auto regexp_expr_arg_lvs = codegen(expr->get_pattern_expr(), true, co);
887  CHECK_EQ(size_t(3), regexp_expr_arg_lvs.size());
888  const bool is_nullable{!expr->get_arg()->get_type_info().get_notnull()};
889  std::vector<llvm::Value*> regexp_args{
890  str_lv[1], str_lv[2], regexp_expr_arg_lvs[1], regexp_expr_arg_lvs[2]};
891  std::string fn_name("regexp_like");
892  regexp_args.push_back(cgen_state_->llInt(int8_t(escape_char)));
893  if (is_nullable) {
894  fn_name += "_nullable";
895  regexp_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
897  fn_name, get_int_type(8, cgen_state_->context_), regexp_args);
898  }
900  fn_name, get_int_type(1, cgen_state_->context_), regexp_args);
901 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const std::shared_ptr< Analyzer::Expr > get_own_arg() const
Definition: Analyzer.h:1134
CgenState * cgen_state_
const Expr * get_escape_expr() const
Definition: Analyzer.h:1136
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
const Expr * get_arg() const
Definition: Analyzer.h:1133
const Analyzer::Expr * extract_cast_arg(const Analyzer::Expr *expr)
Definition: Execute.h:222
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool g_enable_watchdog
llvm::Value * codegenDictRegexp(const std::shared_ptr< Analyzer::Expr > arg, const Analyzer::Constant *pattern, const char escape_char, const CompilationOptions &)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_pattern_expr() const
Definition: Analyzer.h:1135
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1677
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::CardinalityExpr expr,
const CompilationOptions co 
)
private

Definition at line 68 of file ArrayIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), CgenState::context_, CgenState::emitExternalCall(), Analyzer::CardinalityExpr::get_arg(), get_int_type(), Analyzer::Expr::get_type_info(), CgenState::inlineIntNull(), CgenState::llInt(), log2_bytes(), and posArg().

69  {
71  const auto arr_expr = expr->get_arg();
72  const auto& array_ti = arr_expr->get_type_info();
73  CHECK(array_ti.is_array());
74  const auto& elem_ti = array_ti.get_elem_type();
75  auto arr_lv = codegen(arr_expr, true, co);
76  std::string fn_name("array_size");
77 
78  if (auto alloca = llvm::dyn_cast<llvm::AllocaInst>(arr_lv.front())) {
79  if (alloca->getAllocatedType()->isStructTy()) {
80  throw std::runtime_error("Unsupported type used in 'cardinality'");
81  }
82  }
83 
84  std::vector<llvm::Value*> array_size_args{
85  arr_lv.front(),
86  posArg(arr_expr),
87  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))};
88  const bool is_nullable{!arr_expr->get_type_info().get_notnull()};
89  if (is_nullable) {
90  fn_name += "_nullable";
91  array_size_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
92  }
94  fn_name, get_int_type(32, cgen_state_->context_), array_size_args);
95 }
CgenState * cgen_state_
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:198
const Expr * get_arg() const
Definition: Analyzer.h:1007

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::BinOper bin_oper,
const CompilationOptions co 
)
private

Definition at line 234 of file IRCodegen.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenArith(), codegenArrayAt(), codegenCmp(), codegenLogical(), Analyzer::BinOper::get_optype(), IS_ARITHMETIC, IS_COMPARISON, IS_LOGIC, and kARRAY_AT.

235  {
237  const auto optype = bin_oper->get_optype();
238  if (IS_ARITHMETIC(optype)) {
239  return codegenArith(bin_oper, co);
240  }
241  if (IS_COMPARISON(optype)) {
242  return codegenCmp(bin_oper, co);
243  }
244  if (IS_LOGIC(optype)) {
245  return codegenLogical(bin_oper, co);
246  }
247  if (optype == kARRAY_AT) {
248  return codegenArrayAt(bin_oper, co);
249  }
250  abort();
251 }
#define IS_LOGIC(X)
Definition: sqldefs.h:64
llvm::Value * codegenArith(const Analyzer::BinOper *, const CompilationOptions &)
CgenState * cgen_state_
llvm::Value * codegenArrayAt(const Analyzer::BinOper *, const CompilationOptions &)
Definition: ArrayIR.cpp:26
SQLOps get_optype() const
Definition: Analyzer.h:452
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define IS_ARITHMETIC(X)
Definition: sqldefs.h:65
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:230
llvm::Value * codegenLogical(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:299
#define IS_COMPARISON(X)
Definition: sqldefs.h:61

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegen ( const Analyzer::UOper u_oper,
const CompilationOptions co 
)
private

Definition at line 253 of file IRCodegen.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenCast(), codegenIsNull(), codegenLogical(), codegenUMinus(), codegenUnnest(), Analyzer::UOper::get_optype(), kCAST, kISNULL, kNOT, kUMINUS, kUNNEST, and UNREACHABLE.

254  {
256  const auto optype = u_oper->get_optype();
257  switch (optype) {
258  case kNOT: {
259  return codegenLogical(u_oper, co);
260  }
261  case kCAST: {
262  return codegenCast(u_oper, co);
263  }
264  case kUMINUS: {
265  return codegenUMinus(u_oper, co);
266  }
267  case kISNULL: {
268  return codegenIsNull(u_oper, co);
269  }
270  case kUNNEST:
271  return codegenUnnest(u_oper, co);
272  default:
273  UNREACHABLE();
274  }
275  return nullptr;
276 }
CgenState * cgen_state_
#define UNREACHABLE()
Definition: Logger.h:338
Definition: sqldefs.h:51
llvm::Value * codegenIsNull(const Analyzer::UOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:381
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * codegenUMinus(const Analyzer::UOper *, const CompilationOptions &)
llvm::Value * codegenUnnest(const Analyzer::UOper *, const CompilationOptions &)
Definition: ArrayIR.cpp:20
llvm::Value * codegenLogical(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:299
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
Definition: sqldefs.h:41
SQLOps get_optype() const
Definition: Analyzer.h:383

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegenAdd ( const Analyzer::BinOper bin_oper,
llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const std::string &  null_typename,
const std::string &  null_check_suffix,
const SQLTypeInfo ti,
const CompilationOptions co 
)
private

Definition at line 219 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, checkExpressionRanges(), codegenBinOpWithOverflowForCPU(), codegenSkipOverflowCheckForNull(), CgenState::context_, CPU, CgenState::current_func_, CompilationOptions::device_type, CgenState::emitCall(), SQLTypeInfo::get_size(), inline_int_null_val(), CgenState::inlineIntMaxMin(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_timeinterval(), CgenState::llInt(), and CgenState::needs_error_check_.

Referenced by codegenIntArith().

225  {
227  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
228  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
229  llvm::Value* chosen_max{nullptr};
230  llvm::Value* chosen_min{nullptr};
231  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
232  auto need_overflow_check =
233  !checkExpressionRanges(bin_oper,
234  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
235  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
236 
237  if (need_overflow_check && co.device_type == ExecutorDeviceType::CPU) {
239  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
240  }
241 
242  llvm::BasicBlock* add_ok{nullptr};
243  llvm::BasicBlock* add_fail{nullptr};
244  if (need_overflow_check) {
246  add_ok = llvm::BasicBlock::Create(
248  if (!null_check_suffix.empty()) {
249  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, add_ok, ti);
250  }
251  add_fail = llvm::BasicBlock::Create(
253  llvm::Value* detected{nullptr};
254  auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0, true);
255  auto overflow = cgen_state_->ir_builder_.CreateAnd(
256  cgen_state_->ir_builder_.CreateICmpSGT(lhs_lv, const_zero),
257  cgen_state_->ir_builder_.CreateICmpSGT(
258  rhs_lv, cgen_state_->ir_builder_.CreateSub(chosen_max, lhs_lv)));
259  auto underflow = cgen_state_->ir_builder_.CreateAnd(
260  cgen_state_->ir_builder_.CreateICmpSLT(lhs_lv, const_zero),
261  cgen_state_->ir_builder_.CreateICmpSLT(
262  rhs_lv, cgen_state_->ir_builder_.CreateSub(chosen_min, lhs_lv)));
263  detected = cgen_state_->ir_builder_.CreateOr(overflow, underflow);
264  cgen_state_->ir_builder_.CreateCondBr(detected, add_fail, add_ok);
265  cgen_state_->ir_builder_.SetInsertPoint(add_ok);
266  }
267  auto ret = null_check_suffix.empty()
268  ? cgen_state_->ir_builder_.CreateAdd(lhs_lv, rhs_lv)
270  "add_" + null_typename + null_check_suffix,
271  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
272  if (need_overflow_check) {
273  cgen_state_->ir_builder_.SetInsertPoint(add_fail);
274  cgen_state_->ir_builder_.CreateRet(
275  cgen_state_->llInt(int32_t(ErrorCode::OVERFLOW_OR_UNDERFLOW)));
276  cgen_state_->ir_builder_.SetInsertPoint(add_ok);
277  }
278  return ret;
279 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
HOST DEVICE int get_size() const
Definition: sqltypes.h:403
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
bool is_integer() const
Definition: sqltypes.h:567
void codegenSkipOverflowCheckForNull(llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
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)
bool is_timeinterval() const
Definition: sqltypes.h:594
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
ExecutorDeviceType device_type
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool checkExpressionRanges(const Analyzer::UOper *, int64_t, int64_t)
bool is_decimal() const
Definition: sqltypes.h:570
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenArith ( const Analyzer::BinOper bin_oper,
const CompilationOptions co 
)
private

Definition at line 38 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), codegenCastBetweenIntTypes(), codegenDeciDiv(), codegenFpArith(), codegenIntArith(), Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), IS_ARITHMETIC, and kDIVIDE.

Referenced by codegen(), and codegenLinRegPredict().

39  {
41  const auto optype = bin_oper->get_optype();
42  CHECK(IS_ARITHMETIC(optype));
43  const auto lhs = bin_oper->get_left_operand();
44  const auto rhs = bin_oper->get_right_operand();
45  const auto& lhs_type = lhs->get_type_info();
46  const auto& rhs_type = rhs->get_type_info();
47 
48  if (lhs_type.is_decimal() && rhs_type.is_decimal() && optype == kDIVIDE) {
49  const auto ret = codegenDeciDiv(bin_oper, co);
50  if (ret) {
51  return ret;
52  }
53  }
54 
55  auto lhs_lv = codegen(lhs, true, co).front();
56  auto rhs_lv = codegen(rhs, true, co).front();
57  // Handle operations when a time interval operand is involved, an operation
58  // between an integer and a time interval isn't normalized by the analyzer.
59  if (lhs_type.is_timeinterval()) {
60  rhs_lv = codegenCastBetweenIntTypes(rhs_lv, rhs_type, lhs_type);
61  } else if (rhs_type.is_timeinterval()) {
62  lhs_lv = codegenCastBetweenIntTypes(lhs_lv, lhs_type, rhs_type);
63  } else {
64  CHECK_EQ(lhs_type.get_type(), rhs_type.get_type());
65  }
66  if (lhs_type.is_integer() || lhs_type.is_decimal() || lhs_type.is_timeinterval()) {
67  return codegenIntArith(bin_oper, lhs_lv, rhs_lv, co);
68  }
69  if (lhs_type.is_fp()) {
70  return codegenFpArith(bin_oper, lhs_lv, rhs_lv);
71  }
72  CHECK(false);
73  return nullptr;
74 }
llvm::Value * codegenIntArith(const Analyzer::BinOper *, llvm::Value *, llvm::Value *, const CompilationOptions &)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::Value * codegenDeciDiv(const Analyzer::BinOper *, const CompilationOptions &)
llvm::Value * codegenFpArith(const Analyzer::BinOper *, llvm::Value *, llvm::Value *)
SQLOps get_optype() const
Definition: Analyzer.h:452
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:427
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
#define IS_ARITHMETIC(X)
Definition: sqldefs.h:65
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenArrayAt ( const Analyzer::BinOper array_at,
const CompilationOptions co 
)
private

Definition at line 26 of file ArrayIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), CgenState::context_, CgenState::emitExternalCall(), get_int_type(), Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), CgenState::inlineFpNull(), CgenState::inlineIntNull(), CgenState::ir_builder_, kDOUBLE, posArg(), and to_string().

Referenced by codegen().

27  {
29  const auto arr_expr = array_at->get_left_operand();
30  const auto idx_expr = array_at->get_right_operand();
31  const auto& idx_ti = idx_expr->get_type_info();
32  CHECK(idx_ti.is_integer());
33  auto idx_lvs = codegen(idx_expr, true, co);
34  CHECK_EQ(size_t(1), idx_lvs.size());
35  auto idx_lv = idx_lvs.front();
36  if (idx_ti.get_logical_size() < 8) {
37  idx_lv = cgen_state_->ir_builder_.CreateCast(llvm::Instruction::CastOps::SExt,
38  idx_lv,
40  }
41  const auto& array_ti = arr_expr->get_type_info();
42  CHECK(array_ti.is_array());
43  const auto& elem_ti = array_ti.get_elem_type();
44  const std::string array_at_fname{
45  elem_ti.is_fp()
46  ? "array_at_" + std::string(elem_ti.get_type() == kDOUBLE ? "double_checked"
47  : "float_checked")
48  : "array_at_int" + std::to_string(elem_ti.get_logical_size() * 8) +
49  "_t_checked"};
50  const auto ret_ty =
51  elem_ti.is_fp()
52  ? (elem_ti.get_type() == kDOUBLE
53  ? llvm::Type::getDoubleTy(cgen_state_->context_)
54  : llvm::Type::getFloatTy(cgen_state_->context_))
55  : get_int_type(elem_ti.get_logical_size() * 8, cgen_state_->context_);
56  const auto arr_lvs = codegen(arr_expr, true, co);
57  CHECK_EQ(size_t(1), arr_lvs.size());
59  array_at_fname,
60  ret_ty,
61  {arr_lvs.front(),
62  posArg(arr_expr),
63  idx_lv,
64  elem_ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(elem_ti))
65  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(elem_ti))});
66 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string to_string(char const *&&v)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::pair< llvm::Value *, llvm::Value * > CodeGenerator::codegenArrayBuff ( llvm::Value *  chunk,
llvm::Value *  row_pos,
SQLTypes  array_type,
bool  cast_and_extend 
)
private

Definition at line 685 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::context_, CgenState::emitExternalCall(), SQLTypeInfo::get_elem_type(), kARRAY, and kENCODING_NONE.

Referenced by codegenFunctionOperCastArgs().

689  {
691  const auto elem_ti =
692  SQLTypeInfo(
693  SQLTypes::kARRAY, 0, 0, false, EncodingType::kENCODING_NONE, 0, array_type)
694  .get_elem_type();
695 
696  auto buff = cgen_state_->emitExternalCall(
697  "array_buff", llvm::Type::getInt32PtrTy(cgen_state_->context_), {chunk, row_pos});
698 
699  auto len = cgen_state_->emitExternalCall(
700  "array_size",
702  {chunk, row_pos, cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
703 
704  if (cast_and_extend) {
705  buff = castArrayPointer(buff, elem_ti);
706  len =
707  cgen_state_->ir_builder_.CreateZExt(len, get_int_type(64, cgen_state_->context_));
708  }
709 
710  return std::make_pair(buff, len);
711 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * castArrayPointer(llvm::Value *ptr, const SQLTypeInfo &elem_ti)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:198
SQLTypeInfo get_elem_type() const
Definition: sqltypes.h:977

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenArrayExpr ( const Analyzer::ArrayExpr array_expr,
const CompilationOptions co 
)
private

Definition at line 97 of file ArrayIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), CgenState::context_, CompilationOptions::device_type, CgenState::emitExternalCall(), executor(), get_int_array_type(), get_int_type(), Analyzer::Expr::get_type_info(), Analyzer::ArrayExpr::getElement(), Analyzer::ArrayExpr::getElementCount(), GPU, CgenState::ir_builder_, Analyzer::ArrayExpr::isLocalAlloc(), Analyzer::ArrayExpr::isNull(), kENCODING_GEOINT, CgenState::llFp(), and CgenState::llInt().

Referenced by codegen().

99  {
101  using ValueVector = std::vector<llvm::Value*>;
102  ValueVector argument_list;
103  auto& ir_builder(cgen_state_->ir_builder_);
104 
105  const auto& return_type = array_expr->get_type_info();
106  auto coord_compression = (return_type.get_compression() == kENCODING_GEOINT);
107  if (coord_compression) {
108  CHECK(array_expr->isLocalAlloc() && array_expr->getElementCount() == 2);
109  }
110  for (size_t i = 0; i < array_expr->getElementCount(); i++) {
111  const auto arg = array_expr->getElement(i);
112  const auto arg_lvs = codegen(arg, true, co);
113  if (arg_lvs.size() == 1) {
114  if (coord_compression) {
115  // Compress double coords on the fly
116  auto mult = cgen_state_->llFp(2147483647.0 / (i == 0 ? 180.0 : 90.0));
117  auto c = ir_builder.CreateCast(llvm::Instruction::CastOps::FPToSI,
118  ir_builder.CreateFMul(arg_lvs.front(), mult),
120  argument_list.push_back(c);
121  } else {
122  argument_list.push_back(arg_lvs.front());
123  }
124  } else {
125  throw std::runtime_error(
126  "Unexpected argument count during array[] code generation.");
127  }
128  }
129 
130  auto array_element_size_bytes =
131  return_type.get_elem_type().get_array_context_logical_size();
132  auto* array_index_type =
133  get_int_type(array_element_size_bytes * 8, cgen_state_->context_);
134  auto* array_type = get_int_array_type(
135  array_element_size_bytes * 8, array_expr->getElementCount(), cgen_state_->context_);
136 
137  if (array_expr->isNull()) {
138  return {llvm::ConstantPointerNull::get(
139  llvm::PointerType::get(get_int_type(64, cgen_state_->context_), 0)),
140  cgen_state_->llInt(0)};
141  }
142 
143  if (0 == array_expr->getElementCount()) {
144  llvm::Constant* dead_const = cgen_state_->llInt(0xdead);
145  llvm::Value* dead_pointer = llvm::ConstantExpr::getIntToPtr(
146  dead_const, llvm::PointerType::get(get_int_type(64, cgen_state_->context_), 0));
147  return {dead_pointer, cgen_state_->llInt(0)};
148  }
149 
150  llvm::Value* allocated_target_buffer;
151  if (array_expr->isLocalAlloc()) {
152  allocated_target_buffer = ir_builder.CreateAlloca(array_type);
153  } else {
155  throw QueryMustRunOnCpu();
156  }
157 
158  allocated_target_buffer =
159  cgen_state_->emitExternalCall("allocate_varlen_buffer",
160  llvm::Type::getInt8PtrTy(cgen_state_->context_),
161  {cgen_state_->llInt(array_expr->getElementCount()),
162  cgen_state_->llInt(array_element_size_bytes)});
164  "register_buffer_with_executor_rsm",
165  llvm::Type::getVoidTy(cgen_state_->context_),
166  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
167  allocated_target_buffer});
168  }
169  llvm::Value* casted_allocated_target_buffer =
170  ir_builder.CreatePointerCast(allocated_target_buffer, array_type->getPointerTo());
171 
172  for (size_t i = 0; i < array_expr->getElementCount(); i++) {
173  auto* element = argument_list[i];
174  auto* element_ptr = ir_builder.CreateGEP(
175  array_type,
176  casted_allocated_target_buffer,
177  std::vector<llvm::Value*>{cgen_state_->llInt(0), cgen_state_->llInt(i)});
178 
179  const auto& elem_ti = return_type.get_elem_type();
180  if (elem_ti.is_boolean()) {
181  const auto byte_casted_bit =
182  ir_builder.CreateIntCast(element, array_index_type, true);
183  ir_builder.CreateStore(byte_casted_bit, element_ptr);
184  } else if (elem_ti.is_fp()) {
185  switch (elem_ti.get_size()) {
186  case sizeof(double): {
187  const auto double_element_ptr = ir_builder.CreatePointerCast(
188  element_ptr, llvm::Type::getDoublePtrTy(cgen_state_->context_));
189  ir_builder.CreateStore(element, double_element_ptr);
190  break;
191  }
192  case sizeof(float): {
193  const auto float_element_ptr = ir_builder.CreatePointerCast(
194  element_ptr, llvm::Type::getFloatPtrTy(cgen_state_->context_));
195  ir_builder.CreateStore(element, float_element_ptr);
196  break;
197  }
198  default:
199  UNREACHABLE();
200  }
201  } else if (elem_ti.is_integer() || elem_ti.is_decimal() || elem_ti.is_date() ||
202  elem_ti.is_timestamp() || elem_ti.is_time() || elem_ti.is_timeinterval() ||
203  elem_ti.is_dict_encoded_string()) {
204  // TODO(adb): this validation and handling should be done elsewhere
205  const auto sign_extended_element = ir_builder.CreateSExt(element, array_index_type);
206  ir_builder.CreateStore(sign_extended_element, element_ptr);
207  } else {
208  throw std::runtime_error("Unsupported type used in ARRAY construction.");
209  }
210  }
211 
212  return {ir_builder.CreateGEP(
213  array_type, casted_allocated_target_buffer, cgen_state_->llInt(0)),
214  cgen_state_->llInt(array_expr->getElementCount())};
215 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define UNREACHABLE()
Definition: Logger.h:338
bool isNull() const
Definition: Analyzer.h:3025
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
size_t getElementCount() const
Definition: Analyzer.h:3023
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
bool isLocalAlloc() const
Definition: Analyzer.h:3024
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
llvm::ArrayType * get_int_array_type(int const width, int count, llvm::LLVMContext &context)
const Analyzer::Expr * getElement(const size_t i) const
Definition: Analyzer.h:3027
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenBinOpWithOverflowForCPU ( const Analyzer::BinOper bin_oper,
llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const std::string &  null_check_suffix,
const SQLTypeInfo ti 
)
private

Definition at line 728 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenSkipOverflowCheckForNull(), CgenState::context_, CgenState::current_func_, getArithWithOverflowIntrinsic(), inline_int_null_val(), CgenState::ir_builder_, CgenState::llInt(), and CgenState::needs_error_check_.

Referenced by codegenAdd(), codegenMul(), and codegenSub().

733  {
736 
737  llvm::BasicBlock* check_ok = llvm::BasicBlock::Create(
739  llvm::BasicBlock* check_fail = llvm::BasicBlock::Create(
740  cgen_state_->context_, "ovf_detected", cgen_state_->current_func_);
741  llvm::BasicBlock* null_check{nullptr};
742 
743  if (!null_check_suffix.empty()) {
744  null_check = cgen_state_->ir_builder_.GetInsertBlock();
745  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, check_ok, ti);
746  }
747 
748  // Compute result and overflow flag
749  auto func = getArithWithOverflowIntrinsic(bin_oper, lhs_lv->getType());
750  auto ret_and_overflow = cgen_state_->ir_builder_.CreateCall(
751  func, std::vector<llvm::Value*>{lhs_lv, rhs_lv});
752  auto ret = cgen_state_->ir_builder_.CreateExtractValue(ret_and_overflow,
753  std::vector<unsigned>{0});
754  auto overflow = cgen_state_->ir_builder_.CreateExtractValue(ret_and_overflow,
755  std::vector<unsigned>{1});
756  auto val_bb = cgen_state_->ir_builder_.GetInsertBlock();
757 
758  // Return error on overflow
759  cgen_state_->ir_builder_.CreateCondBr(overflow, check_fail, check_ok);
760  cgen_state_->ir_builder_.SetInsertPoint(check_fail);
761  cgen_state_->ir_builder_.CreateRet(
762  cgen_state_->llInt(int32_t(ErrorCode::OVERFLOW_OR_UNDERFLOW)));
763 
764  cgen_state_->ir_builder_.SetInsertPoint(check_ok);
765 
766  // In case of null check we have to use NULL result on check fail
767  if (null_check) {
768  auto phi = cgen_state_->ir_builder_.CreatePHI(ret->getType(), 2);
769  phi->addIncoming(llvm::ConstantInt::get(ret->getType(), inline_int_null_val(ti)),
770  null_check);
771  phi->addIncoming(ret, val_bb);
772  ret = phi;
773  }
774 
775  return ret;
776 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
void codegenSkipOverflowCheckForNull(llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Function * getArithWithOverflowIntrinsic(const Analyzer::BinOper *bin_oper, llvm::Type *type)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenBoundingBoxIntersect ( const SQLOps  optype,
const SQLQualifier  qualifier,
const std::shared_ptr< Analyzer::Expr lhs,
const std::shared_ptr< Analyzer::Expr rhs,
const CompilationOptions co 
)
private

Definition at line 285 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenFunctionOper(), CgenState::context_, g_enable_bbox_intersect_hashjoin, get_int_type(), Catalog_Namespace::get_metadata_for_column(), Datum::intval, IS_GEO_POLY, kBOOLEAN, kDOUBLE, kENCODING_GEOINT, kINT, kPOINT, and VLOG.

Referenced by codegenCmp().

290  {
292  const auto lhs_ti = lhs->get_type_info();
294  // failed to build a suitable hash table. short circuit the bounding box interesect
295  // expression by always returning true. this will fall into the ST_Contains check,
296  // which will do bounding box intersection before the heavier contains computation.
297  VLOG(1) << "Failed to build bounding box intersect hash table, short circuiting "
298  "bounding box intersect operator.";
299  return llvm::ConstantInt::get(get_int_type(8, cgen_state_->context_), true);
300  }
301  // TODO(adb): we should never get here, but going to leave this in place for now since
302  // it will likely be useful in factoring the bounds check out of ST_Contains
303  CHECK(lhs_ti.is_geometry());
304 
305  if (lhs_ti.is_geometry()) {
306  // only point in linestring/poly/mpoly is currently supported
307  CHECK(lhs_ti.get_type() == kPOINT);
308  const auto lhs_col = dynamic_cast<Analyzer::ColumnVar*>(lhs.get());
309  CHECK(lhs_col);
310 
311  // Get the actual point data column descriptor
312  auto lhs_column_key = lhs_col->getColumnKey();
313  lhs_column_key.column_id = lhs_column_key.column_id + 1;
314  const auto coords_cd = Catalog_Namespace::get_metadata_for_column(lhs_column_key);
315  CHECK(coords_cd);
316 
317  std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
318  geoargs.push_back(makeExpr<Analyzer::ColumnVar>(
319  coords_cd->columnType,
320  shared::ColumnKey{lhs_col->getTableKey(), coords_cd->columnId},
321  lhs_col->get_rte_idx()));
322 
323  Datum input_compression;
324  input_compression.intval =
325  (lhs_ti.get_compression() == kENCODING_GEOINT && lhs_ti.get_comp_param() == 32)
326  ? 1
327  : 0;
328  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_compression));
329  Datum input_srid;
330  input_srid.intval = lhs_ti.get_input_srid();
331  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, input_srid));
332  Datum output_srid;
333  output_srid.intval = lhs_ti.get_output_srid();
334  geoargs.push_back(makeExpr<Analyzer::Constant>(kINT, false, output_srid));
335 
336  const auto x_ptr_oper = makeExpr<Analyzer::FunctionOper>(
337  SQLTypeInfo(kDOUBLE, true), "ST_X_Point", geoargs);
338  const auto y_ptr_oper = makeExpr<Analyzer::FunctionOper>(
339  SQLTypeInfo(kDOUBLE, true), "ST_Y_Point", geoargs);
340 
341  const auto rhs_ti = rhs->get_type_info();
342  CHECK(IS_GEO_POLY(rhs_ti.get_type()));
343  const auto rhs_col = dynamic_cast<Analyzer::ColumnVar*>(rhs.get());
344  CHECK(rhs_col);
345 
346  auto rhs_column_key = rhs_col->getColumnKey();
347  rhs_column_key.column_id =
348  rhs_column_key.column_id + rhs_ti.get_physical_coord_cols() + 1;
349  const auto poly_bounds_cd =
351  CHECK(poly_bounds_cd);
352 
353  auto bbox_col_var = makeExpr<Analyzer::ColumnVar>(
354  poly_bounds_cd->columnType,
355  shared::ColumnKey{rhs_col->getTableKey(), poly_bounds_cd->columnId},
356  rhs_col->get_rte_idx());
357 
358  const auto bbox_contains_func_oper =
359  makeExpr<Analyzer::FunctionOper>(SQLTypeInfo(kBOOLEAN, false),
360  "Point_Overlaps_Box",
361  std::vector<std::shared_ptr<Analyzer::Expr>>{
362  bbox_col_var, x_ptr_oper, y_ptr_oper});
363 
364  return codegenFunctionOper(bbox_contains_func_oper.get(), co);
365  }
366 
367  CHECK(false) << "Unsupported type for bounding box intersect operator: "
368  << lhs_ti.get_type_name();
369  return nullptr;
370 }
CgenState * cgen_state_
const ColumnDescriptor * get_metadata_for_column(const ::shared::ColumnKey &column_key)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
int32_t intval
Definition: Datum.h:75
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Value * codegenFunctionOper(const Analyzer::FunctionOper *, const CompilationOptions &)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
bool g_enable_bbox_intersect_hashjoin
Definition: Execute.cpp:109
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
Definition: Datum.h:71
#define VLOG(n)
Definition: Logger.h:388
#define IS_GEO_POLY(T)
Definition: sqltypes.h:315

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenBufferArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  buffer_buf,
llvm::Value *  buffer_size,
llvm::Value *  buffer_is_null,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 713 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, anonymous_namespace{ExtensionsIR.cpp}::get_buffer_struct_type(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

718  {
720  CHECK(buffer_buf);
721  CHECK(buffer_size);
722 
723  auto buffer_abstraction = get_buffer_struct_type(
724  cgen_state_, ext_func_name, param_num, buffer_buf->getType());
725  auto alloc_mem = cgen_state_->ir_builder_.CreateAlloca(buffer_abstraction);
726 
727  auto buffer_buf_ptr =
728  cgen_state_->ir_builder_.CreateStructGEP(buffer_abstraction, alloc_mem, 0);
729  cgen_state_->ir_builder_.CreateStore(buffer_buf, buffer_buf_ptr);
730 
731  auto buffer_size_ptr =
732  cgen_state_->ir_builder_.CreateStructGEP(buffer_abstraction, alloc_mem, 1);
733  cgen_state_->ir_builder_.CreateStore(buffer_size, buffer_size_ptr);
734 
735  auto bool_extended_type = llvm::Type::getInt8Ty(cgen_state_->context_);
736  auto buffer_null_extended =
737  cgen_state_->ir_builder_.CreateZExt(buffer_null, bool_extended_type);
738  auto buffer_is_null_ptr =
739  cgen_state_->ir_builder_.CreateStructGEP(buffer_abstraction, alloc_mem, 2);
740  cgen_state_->ir_builder_.CreateStore(buffer_null_extended, buffer_is_null_ptr);
741  output_args.push_back(alloc_mem);
742 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::StructType * get_buffer_struct_type(CgenState *cgen_state, const std::string &ext_func_name, size_t param_num, llvm::Type *elem_type)
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCase ( const Analyzer::CaseExpr case_expr,
llvm::Type case_llvm_type,
const bool  is_real_str,
const CompilationOptions co 
)
private

Definition at line 65 of file CaseIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, codegen(), CgenState::context_, CgenState::current_func_, CgenState::emitCall(), Analyzer::CaseExpr::get_expr_pair_list(), CgenState::ir_builder_, and toBool().

Referenced by codegen().

68  {
70  // Here the linear control flow will diverge and expressions cached during the
71  // code branch code generation (currently just column decoding) are not going
72  // to be available once we're done generating the case. Take a snapshot of
73  // the cache with FetchCacheAnchor and restore it once we're done with CASE.
75  const auto& expr_pair_list = case_expr->get_expr_pair_list();
76  std::vector<llvm::Value*> then_lvs;
77  std::vector<llvm::BasicBlock*> then_bbs;
78  const auto end_bb = llvm::BasicBlock::Create(
80  for (const auto& expr_pair : expr_pair_list) {
82  const auto when_lv = toBool(codegen(expr_pair.first.get(), true, co).front());
83  const auto cmp_bb = cgen_state_->ir_builder_.GetInsertBlock();
84  const auto then_bb = llvm::BasicBlock::Create(cgen_state_->context_,
85  "then_case",
87  /*insert_before=*/end_bb);
88  cgen_state_->ir_builder_.SetInsertPoint(then_bb);
89  auto then_bb_lvs = codegen(expr_pair.second.get(), true, co);
90  if (is_real_str) {
91  if (then_bb_lvs.size() == 3) {
92  then_lvs.push_back(
93  cgen_state_->emitCall("string_pack", {then_bb_lvs[1], then_bb_lvs[2]}));
94  } else {
95  then_lvs.push_back(then_bb_lvs.front());
96  }
97  } else {
98  CHECK_EQ(size_t(1), then_bb_lvs.size());
99  then_lvs.push_back(then_bb_lvs.front());
100  }
101  then_bbs.push_back(cgen_state_->ir_builder_.GetInsertBlock());
102  cgen_state_->ir_builder_.CreateBr(end_bb);
103  const auto when_bb = llvm::BasicBlock::Create(
105  cgen_state_->ir_builder_.SetInsertPoint(cmp_bb);
106  cgen_state_->ir_builder_.CreateCondBr(when_lv, then_bb, when_bb);
107  cgen_state_->ir_builder_.SetInsertPoint(when_bb);
108  }
109  const auto else_expr = case_expr->get_else_expr();
110  CHECK(else_expr);
111  auto else_lvs = codegen(else_expr, true, co);
112  llvm::Value* else_lv{nullptr};
113  if (else_lvs.size() == 3) {
114  else_lv = cgen_state_->emitCall("string_pack", {else_lvs[1], else_lvs[2]});
115  } else {
116  else_lv = else_lvs.front();
117  }
118  CHECK(else_lv);
119  auto else_bb = cgen_state_->ir_builder_.GetInsertBlock();
120  cgen_state_->ir_builder_.CreateBr(end_bb);
121  cgen_state_->ir_builder_.SetInsertPoint(end_bb);
122  auto then_phi =
123  cgen_state_->ir_builder_.CreatePHI(case_llvm_type, expr_pair_list.size() + 1);
124  CHECK_EQ(then_bbs.size(), then_lvs.size());
125  for (size_t i = 0; i < then_bbs.size(); ++i) {
126  then_phi->addIncoming(then_lvs[i], then_bbs[i]);
127  }
128  then_phi->addIncoming(else_lv, else_bb);
129  return then_phi;
130 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Expr * get_else_expr() const
Definition: Analyzer.h:1387
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
#define CHECK(condition)
Definition: Logger.h:291
const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr > > > & get_expr_pair_list() const
Definition: Analyzer.h:1384

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCast ( const Analyzer::UOper uoper,
const CompilationOptions co 
)
private

Definition at line 21 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, codegen(), CgenState::context_, CgenState::emitCall(), executor_, get_int_type(), Analyzer::UOper::get_operand(), Analyzer::UOper::get_optype(), Analyzer::Expr::get_type_info(), CgenState::ir_builder_, and kCAST.

Referenced by codegen(), codegenCmpDecimalConst(), codegenFunctionOper(), and codegenFunctionOperWithCustomTypeHandling().

22  {
24  CHECK_EQ(uoper->get_optype(), kCAST);
25  const auto& ti = uoper->get_type_info();
26  const auto operand = uoper->get_operand();
27  const auto operand_as_const = dynamic_cast<const Analyzer::Constant*>(operand);
28  // For dictionary encoded constants, the cast holds the dictionary id
29  // information as the compression parameter; handle this case separately.
30  llvm::Value* operand_lv{nullptr};
31  if (operand_as_const) {
32  const auto operand_lvs =
33  codegen(operand_as_const, ti.get_compression(), ti.getStringDictKey(), co);
34  if (operand_lvs.size() == 3) {
35  operand_lv = cgen_state_->emitCall("string_pack", {operand_lvs[1], operand_lvs[2]});
36  } else {
37  operand_lv = operand_lvs.front();
38  }
39  } else {
40  operand_lv = codegen(operand, true, co).front();
41  }
42 
43  // If the operand is a TextEncodingNone struct ({i8*, i64, i8})
44  // unpack it into an int64_t using "string_pack" so that codegenCast
45  // can properly cast it to a TextEncodingDict
46  if (operand_lv->getType()->isPointerTy() &&
47  operand_lv->getType()->getPointerElementType()->isStructTy()) {
48  auto _struct = cgen_state_->ir_builder_.CreateLoad(
49  operand_lv->getType()->getPointerElementType(), operand_lv);
50  auto ptr = cgen_state_->ir_builder_.CreateExtractValue(_struct, {0});
51  auto len = cgen_state_->ir_builder_.CreateTrunc(
52  cgen_state_->ir_builder_.CreateExtractValue(_struct, {1}),
54  executor_->cgen_state_->emitExternalCall(
55  "register_buffer_with_executor_rsm",
56  llvm::Type::getVoidTy(executor_->cgen_state_->context_),
57  {executor_->cgen_state_->llInt(reinterpret_cast<int64_t>(executor_)), ptr});
58  operand_lv = cgen_state_->emitCall("string_pack", {ptr, len});
59  }
60  const auto& operand_ti = operand->get_type_info();
61  return codegenCast(operand_lv, operand_ti, ti, operand_as_const, co);
62 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:51
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
Executor * executor_
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_operand() const
Definition: Analyzer.h:384
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
SQLOps get_optype() const
Definition: Analyzer.h:383

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCast ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti,
const bool  operand_is_const,
const CompilationOptions co 
)
private

Definition at line 73 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, anonymous_namespace{CastIR.cpp}::byte_array_cast(), CgenState::castToTypeIn(), cgen_state_, CHECK, codegenCastBetweenIntTypes(), codegenCastBetweenTimestamps(), codegenCastFromFp(), codegenCastFromString(), codegenCastNonStringToString(), codegenCastTimestampToDate(), codegenCastTimestampToTime(), codegenCastToFp(), CgenState::context_, SQLTypeInfo::get_dimension(), get_int_array_type(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_size(), SQLTypeInfo::get_type(), CgenState::ir_builder_, SQLTypeInfo::is_boolean(), SQLTypeInfo::is_decimal(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_string(), SQLTypeInfo::is_text_encoding_dict(), SQLTypeInfo::is_time(), SQLTypeInfo::is_timestamp(), kDATE, kTIME, and kTIMESTAMP.

77  {
79  if (byte_array_cast(operand_ti, ti)) {
80  auto* byte_array_type = get_int_array_type(8, ti.get_size(), cgen_state_->context_);
81  return cgen_state_->ir_builder_.CreatePointerCast(operand_lv,
82  byte_array_type->getPointerTo());
83  } else if (!operand_ti.is_string() && ti.is_text_encoding_dict()) {
84  return codegenCastNonStringToString(operand_lv, operand_ti, ti, operand_is_const, co);
85  } else if (operand_ti.is_string()) {
86  return codegenCastFromString(operand_lv, operand_ti, ti, operand_is_const, co);
87  } else if (operand_lv->getType()->isIntegerTy()) {
88  CHECK(operand_ti.is_integer() || operand_ti.is_decimal() || operand_ti.is_time() ||
89  operand_ti.is_boolean());
90 
91  if (operand_ti.is_boolean()) {
92  // cast boolean to int8
93  CHECK(operand_lv->getType()->isIntegerTy(1) ||
94  operand_lv->getType()->isIntegerTy(8));
95  if (operand_lv->getType()->isIntegerTy(1)) {
96  operand_lv = cgen_state_->castToTypeIn(operand_lv, 8);
97  }
98  if (ti.is_boolean()) {
99  return operand_lv;
100  }
101  }
102  if (operand_ti.is_integer() && operand_lv->getType()->isIntegerTy(8) &&
103  ti.is_boolean()) {
104  // cast int8 to boolean
105  return codegenCastBetweenIntTypes(operand_lv, operand_ti, ti);
106  }
107  if (operand_ti.get_type() == kTIMESTAMP && ti.get_type() == kDATE) {
108  // Maybe we should instead generate DatetruncExpr directly from RelAlgTranslator
109  // for this pattern. However, DatetruncExpr is supposed to return a timestamp,
110  // whereas this cast returns a date. The underlying type for both is still the same,
111  // but it still doesn't look like a good idea to misuse DatetruncExpr.
112  // Date will have default precision of day, but TIMESTAMP dimension would
113  // matter but while converting date through seconds
115  operand_lv, operand_ti.get_dimension(), !ti.get_notnull());
116  }
117  if (operand_ti.get_type() == kTIMESTAMP && ti.get_type() == kTIME) {
119  operand_lv, operand_ti.get_dimension(), !ti.get_notnull());
120  }
121  if ((operand_ti.get_type() == kTIMESTAMP || operand_ti.get_type() == kDATE) &&
122  ti.get_type() == kTIMESTAMP) {
123  const auto operand_dimen =
124  (operand_ti.is_timestamp()) ? operand_ti.get_dimension() : 0;
125  if (operand_dimen != ti.get_dimension()) {
127  operand_lv, operand_ti, ti, !ti.get_notnull());
128  }
129  }
130  if (ti.is_integer() || ti.is_decimal() || ti.is_time()) {
131  return codegenCastBetweenIntTypes(operand_lv, operand_ti, ti);
132  } else {
133  return codegenCastToFp(operand_lv, operand_ti, ti);
134  }
135  } else {
136  return codegenCastFromFp(operand_lv, operand_ti, ti);
137  }
138  CHECK(false);
139  return nullptr;
140 }
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
llvm::Value * codegenCastFromFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:601
HOST DEVICE int get_size() const
Definition: sqltypes.h:403
Definition: sqltypes.h:76
bool is_timestamp() const
Definition: sqltypes.h:1046
CgenState * cgen_state_
llvm::Value * codegenCastNonStringToString(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const bool operand_is_const, const CompilationOptions &co)
Definition: CastIR.cpp:350
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * codegenCastToFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:558
bool byte_array_cast(const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:66
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
bool is_time() const
Definition: sqltypes.h:579
llvm::LLVMContext & context_
Definition: CgenState.h:382
bool is_integer() const
Definition: sqltypes.h:567
bool is_text_encoding_dict() const
Definition: sqltypes.h:617
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:427
bool is_boolean() const
Definition: sqltypes.h:582
llvm::Value * codegenCastTimestampToDate(llvm::Value *ts_lv, const int dimen, const bool nullable)
Definition: CastIR.cpp:162
#define AUTOMATIC_IR_METADATA(CGENSTATE)
Definition: sqltypes.h:80
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
llvm::Value * codegenCastBetweenTimestamps(llvm::Value *ts_lv, const SQLTypeInfo &operand_dimen, const SQLTypeInfo &target_dimen, const bool nullable)
Definition: CastIR.cpp:199
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * codegenCastTimestampToTime(llvm::Value *ts_lv, const int dimen, const bool nullable)
Definition: CastIR.cpp:142
llvm::Value * codegenCastFromString(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const bool operand_is_const, const CompilationOptions &co)
Definition: CastIR.cpp:231
bool is_string() const
Definition: sqltypes.h:561
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
llvm::ArrayType * get_int_array_type(int const width, int count, llvm::LLVMContext &context)
bool is_decimal() const
Definition: sqltypes.h:570

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegenCastBetweenIntTypes ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti,
bool  upscale = true 
)

Definition at line 427 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenCastBetweenIntTypesOverflowChecks(), CgenState::context_, CgenState::emitCall(), exp_to_scale(), get_bit_width(), get_int_type(), SQLTypeInfo::get_logical_size(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_scale(), inline_int_null_val(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), SQLTypeInfo::is_integer(), kBIGINT, CgenState::llInt(), and numeric_type_name().

Referenced by codegenArith(), codegenCast(), codegenDeciDiv(), codegenWidthBucketExpr(), and Executor::codegenWindowFunctionAggregateCalls().

430  {
432  if (ti.is_decimal() &&
433  (!operand_ti.is_decimal() || operand_ti.get_scale() <= ti.get_scale())) {
434  if (upscale) {
435  if (operand_ti.get_scale() < ti.get_scale()) { // scale only if needed
436  auto scale = exp_to_scale(ti.get_scale() - operand_ti.get_scale());
437  const auto scale_lv =
438  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
439  operand_lv = cgen_state_->ir_builder_.CreateSExt(
440  operand_lv, get_int_type(64, cgen_state_->context_));
441 
442  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, scale);
443 
444  if (operand_ti.get_notnull()) {
445  operand_lv = cgen_state_->ir_builder_.CreateMul(operand_lv, scale_lv);
446  } else {
447  operand_lv = cgen_state_->emitCall(
448  "scale_decimal_up",
449  {operand_lv,
450  scale_lv,
451  cgen_state_->llInt(inline_int_null_val(operand_ti)),
453  }
454  }
455  }
456  } else if (operand_ti.is_decimal()) {
457  // rounded scale down
458  auto scale = (int64_t)exp_to_scale(operand_ti.get_scale() - ti.get_scale());
459  const auto scale_lv =
460  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
461 
462  const auto operand_width =
463  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
464 
465  std::string method_name = "scale_decimal_down_nullable";
466  if (operand_ti.get_notnull()) {
467  method_name = "scale_decimal_down_not_nullable";
468  }
469 
470  CHECK(operand_width == 64);
471  operand_lv = cgen_state_->emitCall(
472  method_name,
473  {operand_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(operand_ti))});
474  }
475  if (ti.is_integer() && operand_ti.is_integer() &&
476  operand_ti.get_logical_size() > ti.get_logical_size()) {
477  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, 1);
478  }
479 
480  const auto operand_width =
481  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
482  const auto target_width = get_bit_width(ti);
483  if (target_width == operand_width) {
484  return operand_lv;
485  }
486  if (operand_ti.get_notnull()) {
487  return cgen_state_->ir_builder_.CreateCast(
488  target_width > operand_width ? llvm::Instruction::CastOps::SExt
489  : llvm::Instruction::CastOps::Trunc,
490  operand_lv,
491  get_int_type(target_width, cgen_state_->context_));
492  }
493  return cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
494  numeric_type_name(ti) + "_nullable",
495  {operand_lv,
496  cgen_state_->inlineIntNull(operand_ti),
497  cgen_state_->inlineIntNull(ti)});
498 }
CgenState * cgen_state_
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:382
int get_logical_size() const
Definition: sqltypes.h:421
bool is_integer() const
Definition: sqltypes.h:567
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
void codegenCastBetweenIntTypesOverflowChecks(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
Definition: CastIR.cpp:500
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
bool is_decimal() const
Definition: sqltypes.h:570

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenCastBetweenIntTypesOverflowChecks ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti,
const int64_t  scale 
)

Definition at line 500 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::context_, CgenState::current_func_, CgenState::emitCall(), get_int_type(), SQLTypeInfo::get_logical_size(), SQLTypeInfo::get_notnull(), inline_int_null_val(), CgenState::inlineIntMaxMin(), CgenState::inlineIntNull(), CgenState::ir_builder_, kBOOLEAN, CgenState::llInt(), CgenState::needs_error_check_, numeric_type_name(), toBool(), and type_name().

Referenced by codegenCastBetweenIntTypes(), and codegenCastBetweenTimestamps().

504  {
506  llvm::Value* chosen_max{nullptr};
507  llvm::Value* chosen_min{nullptr};
508  std::tie(chosen_max, chosen_min) =
510 
512  auto cast_ok = llvm::BasicBlock::Create(
514  auto cast_fail = llvm::BasicBlock::Create(
516  auto operand_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() / scale;
517  auto operand_min = static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue() / scale;
518  const auto ti_llvm_type =
520  llvm::Value* operand_max_lv = llvm::ConstantInt::get(ti_llvm_type, operand_max);
521  llvm::Value* operand_min_lv = llvm::ConstantInt::get(ti_llvm_type, operand_min);
522  const bool is_narrowing = operand_ti.get_logical_size() > ti.get_logical_size();
523  if (is_narrowing) {
524  const auto operand_ti_llvm_type =
526  operand_max_lv =
527  cgen_state_->ir_builder_.CreateSExt(operand_max_lv, operand_ti_llvm_type);
528  operand_min_lv =
529  cgen_state_->ir_builder_.CreateSExt(operand_min_lv, operand_ti_llvm_type);
530  }
531  llvm::Value* over{nullptr};
532  llvm::Value* under{nullptr};
533  if (operand_ti.get_notnull()) {
534  over = cgen_state_->ir_builder_.CreateICmpSGT(operand_lv, operand_max_lv);
535  under = cgen_state_->ir_builder_.CreateICmpSLE(operand_lv, operand_min_lv);
536  } else {
537  const auto type_name =
538  is_narrowing ? numeric_type_name(operand_ti) : numeric_type_name(ti);
539  const auto null_operand_val = cgen_state_->llInt(inline_int_null_val(operand_ti));
540  const auto null_bool_val = cgen_state_->inlineIntNull(SQLTypeInfo(kBOOLEAN, false));
541  over = toBool(cgen_state_->emitCall(
542  "gt_" + type_name + "_nullable_lhs",
543  {operand_lv, operand_max_lv, null_operand_val, null_bool_val}));
544  under = toBool(cgen_state_->emitCall(
545  "le_" + type_name + "_nullable_lhs",
546  {operand_lv, operand_min_lv, null_operand_val, null_bool_val}));
547  }
548  const auto detected = cgen_state_->ir_builder_.CreateOr(over, under, "overflow");
549  cgen_state_->ir_builder_.CreateCondBr(detected, cast_fail, cast_ok);
550 
551  cgen_state_->ir_builder_.SetInsertPoint(cast_fail);
552  cgen_state_->ir_builder_.CreateRet(
553  cgen_state_->llInt(int32_t(heavyai::ErrorCode::OVERFLOW_OR_UNDERFLOW)));
554 
555  cgen_state_->ir_builder_.SetInsertPoint(cast_ok);
556 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
int get_logical_size() const
Definition: sqltypes.h:421
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
constexpr auto type_name() noexcept
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastBetweenTimestamps ( llvm::Value *  ts_lv,
const SQLTypeInfo operand_dimen,
const SQLTypeInfo target_dimen,
const bool  nullable 
)

Definition at line 199 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenCastBetweenIntTypesOverflowChecks(), CgenState::emitCall(), SQLTypeInfo::get_dimension(), DateTimeUtils::get_timestamp_precision_scale(), CgenState::inlineIntNull(), CgenState::ir_builder_, and CgenState::llInt().

Referenced by codegenCast().

202  {
204  const auto operand_dimen = operand_ti.get_dimension();
205  const auto target_dimen = target_ti.get_dimension();
206  if (operand_dimen == target_dimen) {
207  return ts_lv;
208  }
209  CHECK(ts_lv->getType()->isIntegerTy(64));
210  const auto scale =
211  DateTimeUtils::get_timestamp_precision_scale(abs(operand_dimen - target_dimen));
212  if (operand_dimen < target_dimen) {
213  codegenCastBetweenIntTypesOverflowChecks(ts_lv, operand_ti, target_ti, scale);
214  return nullable
215  ? cgen_state_->emitCall("mul_int64_t_nullable_lhs",
216  {ts_lv,
217  cgen_state_->llInt(static_cast<int64_t>(scale)),
218  cgen_state_->inlineIntNull(operand_ti)})
219  : cgen_state_->ir_builder_.CreateMul(
220  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
221  }
222  return nullable
223  ? cgen_state_->emitCall("floor_div_nullable_lhs",
224  {ts_lv,
225  cgen_state_->llInt(static_cast<int64_t>(scale)),
226  cgen_state_->inlineIntNull(operand_ti)})
227  : cgen_state_->ir_builder_.CreateSDiv(
228  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
229 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
void codegenCastBetweenIntTypesOverflowChecks(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
Definition: CastIR.cpp:500
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastFromFp ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti 
)
private

Definition at line 601 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, CgenState::emitCall(), get_bit_width(), get_int_type(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_type(), SQLTypeInfo::get_type_name(), CgenState::inlineFpNull(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), SQLTypeInfo::is_fp(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_number(), kDOUBLE, kFLOAT, and numeric_type_name().

Referenced by codegenCast().

603  {
605  if (!operand_ti.is_fp() || !ti.is_number() || ti.is_decimal()) {
606  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
607  ti.get_type_name() + " not supported");
608  }
609  if (operand_ti.get_type() == ti.get_type()) {
610  // Should not have been called when both dimensions are same.
611  return operand_lv;
612  }
613  CHECK(operand_lv->getType()->isFloatTy() || operand_lv->getType()->isDoubleTy());
614  if (operand_ti.get_notnull()) {
615  if (ti.get_type() == kDOUBLE) {
616  return cgen_state_->ir_builder_.CreateFPExt(
617  operand_lv, llvm::Type::getDoubleTy(cgen_state_->context_));
618  } else if (ti.get_type() == kFLOAT) {
619  return cgen_state_->ir_builder_.CreateFPTrunc(
620  operand_lv, llvm::Type::getFloatTy(cgen_state_->context_));
621  } else if (ti.is_integer()) {
622  // Round by adding/subtracting 0.5 before fptosi.
623  auto* fp_type = operand_lv->getType()->isFloatTy()
624  ? llvm::Type::getFloatTy(cgen_state_->context_)
625  : llvm::Type::getDoubleTy(cgen_state_->context_);
626  auto* zero = llvm::ConstantFP::get(fp_type, 0.0);
627  auto* mhalf = llvm::ConstantFP::get(fp_type, -0.5);
628  auto* phalf = llvm::ConstantFP::get(fp_type, 0.5);
629  auto* is_negative = cgen_state_->ir_builder_.CreateFCmpOLT(operand_lv, zero);
630  auto* offset = cgen_state_->ir_builder_.CreateSelect(is_negative, mhalf, phalf);
631  operand_lv = cgen_state_->ir_builder_.CreateFAdd(operand_lv, offset);
632  return cgen_state_->ir_builder_.CreateFPToSI(
633  operand_lv, get_int_type(get_bit_width(ti), cgen_state_->context_));
634  } else {
635  CHECK(false);
636  }
637  } else {
638  const auto from_tname = numeric_type_name(operand_ti);
639  const auto to_tname = numeric_type_name(ti);
640  if (ti.is_fp()) {
641  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
642  {operand_lv,
643  cgen_state_->inlineFpNull(operand_ti),
644  cgen_state_->inlineFpNull(ti)});
645  } else if (ti.is_integer()) {
646  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
647  {operand_lv,
648  cgen_state_->inlineFpNull(operand_ti),
649  cgen_state_->inlineIntNull(ti)});
650  } else {
651  CHECK(false);
652  }
653  }
654  CHECK(false);
655  return nullptr;
656 }
CgenState * cgen_state_
bool is_fp() const
Definition: sqltypes.h:573
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool is_number() const
Definition: sqltypes.h:576
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:382
bool is_integer() const
Definition: sqltypes.h:567
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::string get_type_name() const
Definition: sqltypes.h:484
#define CHECK(condition)
Definition: Logger.h:291
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
bool is_decimal() const
Definition: sqltypes.h:570
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastFromString ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti,
const bool  operand_is_const,
const CompilationOptions co 
)
private

Definition at line 231 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, StringDictionaryTranslationMgr::codegen(), CgenState::context_, CPU, Data_Namespace::CPU_LEVEL, createStringViewStructType(), CompilationOptions::device_type, shared::StringDictKey::dict_id, CgenState::emitExternalCall(), executor(), g_cluster, SQLTypeInfo::get_compression(), get_int_type(), SQLTypeInfo::get_type_name(), SQLTypeInfo::getStringDictKey(), GPU, Data_Namespace::GPU_LEVEL, SQLTypeInfo::is_dict_intersection(), SQLTypeInfo::is_string(), kENCODING_DICT, kENCODING_NONE, dict_ref_t::literalsDictId, CgenState::llInt(), and CgenState::moveStringDictionaryTranslationMgr().

Referenced by codegenCast().

235  {
237  if (!ti.is_string()) {
238  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
239  ti.get_type_name() + " not supported");
240  }
241  if (operand_ti.get_compression() == kENCODING_NONE &&
243  return operand_lv;
244  }
245  if (ti.get_compression() == kENCODING_DICT &&
246  operand_ti.get_compression() == kENCODING_DICT) {
247  if (ti.getStringDictKey() == operand_ti.getStringDictKey()) {
248  return operand_lv;
249  }
250  if (operand_ti.getStringDictKey().dict_id == DictRef::literalsDictId) {
251  // Anything being casted from a literal dictionary is not materialized at this point
252  // Should already have been kicked to CPU if it was originally a GPU query
253 
255  const int64_t source_string_proxy_handle =
256  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
257  operand_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true));
258 
259  const int64_t dest_string_proxy_handle =
260  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
261  ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true));
262 
263  auto source_string_proxy_handle_lv = cgen_state_->llInt(source_string_proxy_handle);
264  auto dest_string_proxy_handle_lv = cgen_state_->llInt(dest_string_proxy_handle);
265 
266  std::vector<llvm::Value*> string_cast_lvs{
267  operand_lv, source_string_proxy_handle_lv, dest_string_proxy_handle_lv};
268  if (ti.is_dict_intersection()) {
270  "intersect_translate_string_id_to_other_dict",
272  string_cast_lvs);
273  } else {
274  return cgen_state_->emitExternalCall("union_translate_string_id_to_other_dict",
276  string_cast_lvs);
277  }
278  }
279 
280  const std::vector<StringOps_Namespace::StringOpInfo> string_op_infos;
281  auto string_dictionary_translation_mgr =
282  std::make_unique<StringDictionaryTranslationMgr>(
283  operand_ti.getStringDictKey(),
284  ti.getStringDictKey(),
286  ti,
287  string_op_infos,
290  executor()->deviceCount(co.device_type),
291  executor(),
292  executor()->getDataMgr(),
293  false /* delay_translation */);
294 
295  return cgen_state_
296  ->moveStringDictionaryTranslationMgr(std::move(string_dictionary_translation_mgr))
297  ->codegen(operand_lv, operand_ti, true /* add_nullcheck */, co);
298  }
299  // dictionary encode non-constant
300  if (operand_ti.get_compression() != kENCODING_DICT && !operand_is_const) {
301  if (g_cluster) {
302  throw std::runtime_error(
303  "Cast from none-encoded string to dictionary-encoded not supported for "
304  "distributed queries");
305  }
306  CHECK_EQ(kENCODING_NONE, operand_ti.get_compression());
308  CHECK(operand_lv->getType()->isStructTy()); // StringView
310  throw QueryMustRunOnCpu();
311  }
313  "string_compress",
315  {operand_lv,
316  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
317  ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true)))});
318  }
319  CHECK(operand_lv->getType()->isIntegerTy(32));
320  if (ti.get_compression() == kENCODING_NONE) {
321  if (g_cluster) {
322  throw std::runtime_error(
323  "Cast from dictionary-encoded string to none-encoded not "
324  "currently supported for distributed queries.");
325  }
326  // Removed watchdog check here in exchange for row cardinality based check in
327  // RelAlgExecutor
328  CHECK_EQ(kENCODING_DICT, operand_ti.get_compression());
330  throw QueryMustRunOnCpu();
331  }
332  const int64_t string_dictionary_ptr =
333  operand_ti.getStringDictKey().dict_id == 0
334  ? reinterpret_cast<int64_t>(
335  executor()->getRowSetMemoryOwner()->getLiteralStringDictProxy())
336  : reinterpret_cast<int64_t>(
337  executor()->getStringDictionaryProxy(operand_ti.getStringDictKey(),
338  executor()->getRowSetMemoryOwner(),
339  true));
341  "string_decompress",
343  {operand_lv, cgen_state_->llInt(string_dictionary_ptr)});
344  }
345  CHECK(operand_is_const);
347  return operand_lv;
348 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
bool is_dict_intersection() const
Definition: sqltypes.h:660
#define AUTOMATIC_IR_METADATA(CGENSTATE)
ExecutorDeviceType device_type
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
llvm::StructType * createStringViewStructType()
std::string get_type_name() const
Definition: sqltypes.h:484
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool g_cluster
const StringDictionaryTranslationMgr * moveStringDictionaryTranslationMgr(std::unique_ptr< const StringDictionaryTranslationMgr > &&str_dict_translation_mgr)
Definition: CgenState.h:199
bool is_string() const
Definition: sqltypes.h:561
llvm::Value * codegen(llvm::Value *str_id_input, const SQLTypeInfo &input_ti, const bool add_nullcheck, const CompilationOptions &co) const
static constexpr int32_t literalsDictId
Definition: DictRef.h:18
const shared::StringDictKey & getStringDictKey() const
Definition: sqltypes.h:1057
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastNonStringToString ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti,
const bool  operand_is_const,
const CompilationOptions co 
)
private

Definition at line 350 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, CompilationOptions::device_type, CgenState::emitExternalCall(), executor(), g_cluster, SQLTypeInfo::get_compression(), SQLTypeInfo::get_dimension(), get_int_type(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_precision(), SQLTypeInfo::get_scale(), SQLTypeInfo::get_type(), SQLTypeInfo::getStringDictKey(), GPU, SQLTypeInfo::is_string(), kBIGINT, kBOOLEAN, kDATE, kDECIMAL, kDOUBLE, kENCODING_NONE, kFLOAT, kINT, kNUMERIC, kSMALLINT, kTIME, kTIMESTAMP, kTINYINT, CgenState::llInt(), to_lower(), and toString().

Referenced by codegenCast().

354  {
356  CHECK(!operand_ti.is_string());
357  if (ti.get_compression() == kENCODING_NONE) {
358  throw std::runtime_error("Cast to none-encoded strings currently unsupported.");
359  }
360  if (g_cluster) {
361  throw std::runtime_error(
362  "Cast to dictionary-encoded string type not supported for "
363  "distributed queries");
364  }
366  throw QueryMustRunOnCpu();
367  }
368  std::string fn_call{"convert_to_string_and_encode_"};
369  const auto operand_type = operand_ti.get_type();
370  std::vector operand_lvs{operand_lv};
371  switch (operand_type) {
372  case kBOOLEAN:
373  fn_call += "bool";
374  break;
375  case kTINYINT:
376  case kSMALLINT:
377  case kINT:
378  case kBIGINT:
379  case kFLOAT:
380  case kDOUBLE:
381  fn_call += to_lower(toString(operand_type));
382  break;
383  case kNUMERIC:
384  case kDECIMAL:
385  fn_call += "decimal";
386  operand_lvs.emplace_back(llvm::ConstantInt::get(
387  get_int_type(32, cgen_state_->context_), operand_ti.get_precision()));
388  operand_lvs.emplace_back(llvm::ConstantInt::get(
389  get_int_type(32, cgen_state_->context_), operand_ti.get_scale()));
390  break;
391  case kTIME:
392  fn_call += "time";
393  break;
394  case kTIMESTAMP:
395  fn_call += "timestamp";
396  operand_lvs.emplace_back(llvm::ConstantInt::get(
397  get_int_type(32, cgen_state_->context_), operand_ti.get_dimension()));
398  break;
399  case kDATE:
400  fn_call += "date";
401  break;
402  default:
403  throw std::runtime_error("Unimplemented type for string cast");
404  }
405  operand_lvs.emplace_back(
406  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
407  ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true))));
408 
409  auto ret = cgen_state_->emitExternalCall(
410  fn_call, get_int_type(32, cgen_state_->context_), operand_lvs);
411 
412  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
413  const bool is_nullable = !operand_ti.get_notnull();
414  if (is_nullable) {
415  nullcheck_codegen =
416  std::make_unique<NullCheckCodegen>(cgen_state_,
417  executor(),
418  operand_lvs.front(),
419  operand_ti,
420  "cast_non_string_to_string_nullcheck");
421  CHECK(nullcheck_codegen);
422  ret = nullcheck_codegen->finalize(cgen_state_->inlineNull(ti), ret);
423  }
424  return ret;
425 }
std::string to_lower(const std::string &str)
Definition: sqltypes.h:76
CgenState * cgen_state_
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
int get_precision() const
Definition: sqltypes.h:394
ExecutorDeviceType device_type
Definition: sqltypes.h:80
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool g_cluster
Definition: sqltypes.h:72
bool is_string() const
Definition: sqltypes.h:561
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
const shared::StringDictKey & getStringDictKey() const
Definition: sqltypes.h:1057
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastTimestampToDate ( llvm::Value *  ts_lv,
const int  dimen,
const bool  nullable 
)
private

Definition at line 162 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, CgenState::emitExternalCall(), get_int_type(), DateTimeUtils::get_timestamp_precision_scale(), CgenState::inlineIntNull(), kBIGINT, and CgenState::llInt().

Referenced by codegenCast().

164  {
166  CHECK(ts_lv->getType()->isIntegerTy(64));
167  if (dimen > 0) {
168  if (nullable) {
170  "DateTruncateHighPrecisionToDateNullable",
172  {{ts_lv,
175  }
177  "DateTruncateHighPrecisionToDate",
179  {{ts_lv,
181  }
182  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
183  if (nullable) {
184  nullcheck_codegen =
185  std::make_unique<NullCheckCodegen>(cgen_state_,
186  executor(),
187  ts_lv,
188  SQLTypeInfo(kTIMESTAMP, dimen, 0, !nullable),
189  "cast_timestamp_nullcheck");
190  }
191  auto ret = cgen_state_->emitExternalCall(
192  "datetrunc_day", get_int_type(64, cgen_state_->context_), {ts_lv});
193  if (nullcheck_codegen) {
194  ret = nullcheck_codegen->finalize(ll_int(NULL_BIGINT, cgen_state_->context_), ret);
195  }
196  return ret;
197 }
CgenState * cgen_state_
#define NULL_BIGINT
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastTimestampToTime ( llvm::Value *  ts_lv,
const int  dimen,
const bool  nullable 
)
private

Definition at line 142 of file CastIR.cpp.

References cgen_state_, CgenState::context_, CgenState::emitExternalCall(), get_int_type(), DateTimeUtils::get_timestamp_precision_scale(), CgenState::inlineIntNull(), kBIGINT, and CgenState::llInt().

Referenced by codegenCast().

144  {
145  std::vector<llvm::Value*> datetrunc_args{ts_lv};
146  std::string hptodate_fname;
147  if (dimen > 0) {
148  hptodate_fname = "ExtractTimeFromHPTimestamp";
149  datetrunc_args.push_back(
151  } else {
152  hptodate_fname = "ExtractTimeFromLPTimestamp";
153  }
154  if (nullable) {
155  datetrunc_args.push_back(cgen_state_->inlineIntNull(SQLTypeInfo(kBIGINT, false)));
156  hptodate_fname += "Nullable";
157  }
159  hptodate_fname, get_int_type(64, cgen_state_->context_), datetrunc_args);
160 }
CgenState * cgen_state_
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCastToFp ( llvm::Value *  operand_lv,
const SQLTypeInfo operand_ti,
const SQLTypeInfo ti 
)
private

Definition at line 558 of file CastIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, CgenState::emitCall(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_scale(), SQLTypeInfo::get_type(), SQLTypeInfo::get_type_name(), CgenState::inlineFpNull(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_fp(), kFLOAT, numeric_type_name(), and shared::power10().

Referenced by codegenCast().

560  {
562  if (!ti.is_fp()) {
563  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
564  ti.get_type_name() + " not supported");
565  }
566  llvm::Value* result_lv;
567  if (operand_ti.get_notnull()) {
568  auto const fp_type = ti.get_type() == kFLOAT
569  ? llvm::Type::getFloatTy(cgen_state_->context_)
570  : llvm::Type::getDoubleTy(cgen_state_->context_);
571  result_lv = cgen_state_->ir_builder_.CreateSIToFP(operand_lv, fp_type);
572  if (auto const scale = static_cast<unsigned>(operand_ti.get_scale())) {
573  double const divider = shared::power10(scale);
574  result_lv = cgen_state_->ir_builder_.CreateFDiv(
575  result_lv, llvm::ConstantFP::get(result_lv->getType(), divider));
576  }
577  } else {
578  if (auto const scale = static_cast<unsigned>(operand_ti.get_scale())) {
579  double const divider = shared::power10(scale);
580  auto const fp_type = ti.get_type() == kFLOAT
581  ? llvm::Type::getFloatTy(cgen_state_->context_)
582  : llvm::Type::getDoubleTy(cgen_state_->context_);
583  result_lv = cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
584  numeric_type_name(ti) + "_scaled_nullable",
585  {operand_lv,
586  cgen_state_->inlineIntNull(operand_ti),
588  llvm::ConstantFP::get(fp_type, divider)});
589  } else {
590  result_lv = cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
591  numeric_type_name(ti) + "_nullable",
592  {operand_lv,
593  cgen_state_->inlineIntNull(operand_ti),
594  cgen_state_->inlineFpNull(ti)});
595  }
596  }
597  CHECK(result_lv);
598  return result_lv;
599 }
double power10(unsigned const x)
Definition: misc.h:284
CgenState * cgen_state_
bool is_fp() const
Definition: sqltypes.h:573
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::string get_type_name() const
Definition: sqltypes.h:484
#define CHECK(condition)
Definition: Logger.h:291
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCmp ( const Analyzer::BinOper bin_oper,
const CompilationOptions co 
)
private

Definition at line 230 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, anonymous_namespace{CompareIR.cpp}::check_array_comp_cond(), CHECK_EQ, codegen(), codegenBoundingBoxIntersect(), codegenCmpDecimalConst(), codegenLogical(), codegenStrCmp(), Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_own_left_operand(), Analyzer::BinOper::get_own_right_operand(), Analyzer::BinOper::get_qualifier(), Analyzer::BinOper::get_right_operand(), IS_EQUIVALENCE, is_unnest(), kBBOX_INTERSECT, kBW_EQ, kNE, anonymous_namespace{CompareIR.cpp}::lower_bw_eq(), and anonymous_namespace{CompareIR.cpp}::lower_multicol_compare().

Referenced by codegen(), codegenCmpDecimalConst(), and codegenWidthBucketExpr().

231  {
233  const auto qualifier = bin_oper->get_qualifier();
234  const auto lhs = bin_oper->get_left_operand();
235  const auto rhs = bin_oper->get_right_operand();
236  if (dynamic_cast<const Analyzer::ExpressionTuple*>(lhs)) {
237  CHECK(dynamic_cast<const Analyzer::ExpressionTuple*>(rhs));
238  const auto lowered = lower_multicol_compare(bin_oper);
239  const auto lowered_lvs = codegen(lowered.get(), true, co);
240  CHECK_EQ(size_t(1), lowered_lvs.size());
241  return lowered_lvs.front();
242  }
243  const auto optype = bin_oper->get_optype();
244  if (optype == kBW_EQ) {
245  const auto bw_eq_oper = lower_bw_eq(bin_oper);
246  return codegenLogical(bw_eq_oper.get(), co);
247  }
248  if (optype == kBBOX_INTERSECT) {
249  return codegenBoundingBoxIntersect(optype,
250  qualifier,
251  bin_oper->get_own_left_operand(),
252  bin_oper->get_own_right_operand(),
253  co);
254  }
255  if (is_unnest(lhs) || is_unnest(rhs)) {
256  throw std::runtime_error("Unnest not supported in comparisons");
257  }
258  check_array_comp_cond(bin_oper);
259  const auto& lhs_ti = lhs->get_type_info();
260  const auto& rhs_ti = rhs->get_type_info();
261 
262  if (lhs_ti.is_string() && rhs_ti.is_string() &&
263  !(IS_EQUIVALENCE(optype) || optype == kNE)) {
264  auto cmp_str = codegenStrCmp(optype,
265  qualifier,
266  bin_oper->get_own_left_operand(),
267  bin_oper->get_own_right_operand(),
268  co);
269  if (cmp_str) {
270  return cmp_str;
271  }
272  }
273 
274  if (lhs_ti.is_decimal()) {
275  auto cmp_decimal_const =
276  codegenCmpDecimalConst(optype, qualifier, lhs, lhs_ti, rhs, co);
277  if (cmp_decimal_const) {
278  return cmp_decimal_const;
279  }
280  }
281  auto lhs_lvs = codegen(lhs, true, co);
282  return codegenCmp(optype, qualifier, lhs_lvs, lhs_ti, rhs, co);
283 }
void check_array_comp_cond(const Analyzer::BinOper *bin_oper)
Definition: CompareIR.cpp:182
#define CHECK_EQ(x, y)
Definition: Logger.h:301
llvm::Value * codegenStrCmp(const SQLOps, const SQLQualifier, const std::shared_ptr< Analyzer::Expr >, const std::shared_ptr< Analyzer::Expr >, const CompilationOptions &)
Definition: CompareIR.cpp:372
#define IS_EQUIVALENCE(X)
Definition: sqldefs.h:72
CgenState * cgen_state_
std::shared_ptr< Analyzer::BinOper > lower_multicol_compare(const Analyzer::BinOper *multicol_compare)
Definition: CompareIR.cpp:159
const Expr * get_right_operand() const
Definition: Analyzer.h:456
std::shared_ptr< Analyzer::BinOper > lower_bw_eq(const Analyzer::BinOper *bw_eq)
Definition: CompareIR.cpp:125
SQLOps get_optype() const
Definition: Analyzer.h:452
llvm::Value * codegenCmpDecimalConst(const SQLOps, const SQLQualifier, const Analyzer::Expr *, const SQLTypeInfo &, const Analyzer::Expr *, const CompilationOptions &)
Definition: CompareIR.cpp:402
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqldefs.h:34
llvm::Value * codegenBoundingBoxIntersect(const SQLOps, const SQLQualifier, const std::shared_ptr< Analyzer::Expr >, const std::shared_ptr< Analyzer::Expr >, const CompilationOptions &)
Definition: CompareIR.cpp:285
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:230
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:33
llvm::Value * codegenLogical(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:299
const Expr * get_left_operand() const
Definition: Analyzer.h:455
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1677
const std::shared_ptr< Analyzer::Expr > get_own_right_operand() const
Definition: Analyzer.h:460
const std::shared_ptr< Analyzer::Expr > get_own_left_operand() const
Definition: Analyzer.h:457
SQLQualifier get_qualifier() const
Definition: Analyzer.h:454

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCmp ( const SQLOps  optype,
const SQLQualifier  qualifier,
std::vector< llvm::Value * >  lhs_lvs,
const SQLTypeInfo lhs_ti,
const Analyzer::Expr rhs,
const CompilationOptions co 
)
private

Definition at line 482 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, CgenState::castToTypeIn(), cgen_state_, CHECK, CHECK_EQ, codegen(), codegenQualifierCmp(), createStringViewStructType(), CgenState::emitCall(), executor_, SQLTypeInfo::get_compression(), get_null_check_suffix(), SQLTypeInfo::get_type(), Analyzer::Expr::get_type_info(), anonymous_namespace{CompareIR.cpp}::icmp_name(), inline_int_null_val(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_boolean(), IS_COMPARISON, SQLTypeInfo::is_decimal(), IS_EQUIVALENCE, SQLTypeInfo::is_geometry(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_string(), SQLTypeInfo::is_time(), SQLTypeInfo::is_timeinterval(), kBBOX_INTERSECT, kBOOLEAN, kDOUBLE, kENCODING_DICT, kENCODING_NONE, kFLOAT, kNE, kONE, CgenState::llFp(), CgenState::llInt(), anonymous_namespace{CompareIR.cpp}::llvm_fcmp_pred(), anonymous_namespace{CompareIR.cpp}::llvm_icmp_pred(), NULL_DOUBLE, NULL_FLOAT, numeric_type_name(), anonymous_namespace{CompareIR.cpp}::string_cmp_func(), anonymous_namespace{CompareIR.cpp}::unpack_dict_encoded_string(), and anonymous_namespace{CompareIR.cpp}::unpack_none_encoded_string().

487  {
489  CHECK(IS_COMPARISON(optype));
490  const auto& rhs_ti = rhs->get_type_info();
491  if (rhs_ti.is_array()) {
492  return codegenQualifierCmp(optype, qualifier, lhs_lvs, rhs, co);
493  }
494  auto rhs_lvs = codegen(rhs, true, co);
495  CHECK_EQ(kONE, qualifier);
496  if (optype == kBBOX_INTERSECT) {
497  CHECK(lhs_ti.is_geometry());
498  CHECK(rhs_ti.is_array() ||
499  rhs_ti.is_geometry()); // allow geo col or bounds col to pass
500  } else {
501  CHECK((lhs_ti.get_type() == rhs_ti.get_type()) ||
502  (lhs_ti.is_string() && rhs_ti.is_string()));
503  }
504  const auto null_check_suffix = get_null_check_suffix(lhs_ti, rhs_ti);
505  if (lhs_ti.is_integer() || lhs_ti.is_decimal() || lhs_ti.is_time() ||
506  lhs_ti.is_boolean() || lhs_ti.is_string() || lhs_ti.is_timeinterval()) {
507  if (lhs_ti.is_string()) {
508  CHECK(rhs_ti.is_string());
509  // we sync two string col's encoding scheme
510  // if one of them is dict-encoded before reaching here,
511  // i.e., call `codegenCastNonStringToString` or `codegenCastFromString`
512  CHECK_EQ(lhs_ti.get_compression(), rhs_ti.get_compression());
513  bool unpack_strings = true;
514  if (lhs_ti.get_compression() == kENCODING_NONE) {
517  } else if (lhs_ti.get_compression() == kENCODING_DICT) {
518  if (IS_EQUIVALENCE(optype) || optype == kNE) {
519  // we use `StringDictionaryTranslationMgr` to translate
520  // dict-encoded lhs against rhs's string dictionary
521  // and then compare their string ids without unpacking strings
522  // i.e., call `eq_int32_t_nullable` instead of `string_eq_nullable`
523  unpack_strings = false;
524  } else {
525  auto sv_struct_type_lv = createStringViewStructType();
527  cgen_state_, executor_, lhs_ti, sv_struct_type_lv, lhs_lvs);
529  cgen_state_, executor_, rhs_ti, sv_struct_type_lv, rhs_lvs);
530  }
531  }
532  if (unpack_strings) {
533  // we directly compare two unpacked (i.e., raw) strings
534  std::vector<llvm::Value*> str_cmp_args{
535  lhs_lvs[1], lhs_lvs[2], rhs_lvs[1], rhs_lvs[2]};
536  if (!null_check_suffix.empty()) {
537  str_cmp_args.push_back(
539  }
540  return cgen_state_->emitCall(
541  string_cmp_func(optype) + (null_check_suffix.empty() ? "" : "_nullable"),
542  str_cmp_args);
543  }
544  }
545 
546  if (lhs_ti.is_boolean() && rhs_ti.is_boolean()) {
547  auto& lhs_lv = lhs_lvs.front();
548  auto& rhs_lv = rhs_lvs.front();
549  CHECK(lhs_lv->getType()->isIntegerTy());
550  CHECK(rhs_lv->getType()->isIntegerTy());
551  if (lhs_lv->getType()->getIntegerBitWidth() <
552  rhs_lv->getType()->getIntegerBitWidth()) {
553  lhs_lv =
554  cgen_state_->castToTypeIn(lhs_lv, rhs_lv->getType()->getIntegerBitWidth());
555  } else {
556  rhs_lv =
557  cgen_state_->castToTypeIn(rhs_lv, lhs_lv->getType()->getIntegerBitWidth());
558  }
559  }
560 
561  return null_check_suffix.empty()
562  ? cgen_state_->ir_builder_.CreateICmp(
563  llvm_icmp_pred(optype), lhs_lvs.front(), rhs_lvs.front())
565  icmp_name(optype) + "_" + numeric_type_name(lhs_ti) +
566  null_check_suffix,
567  {lhs_lvs.front(),
568  rhs_lvs.front(),
571  }
572  if (lhs_ti.get_type() == kFLOAT || lhs_ti.get_type() == kDOUBLE) {
573  return null_check_suffix.empty()
574  ? cgen_state_->ir_builder_.CreateFCmp(
575  llvm_fcmp_pred(optype), lhs_lvs.front(), rhs_lvs.front())
577  icmp_name(optype) + "_" + numeric_type_name(lhs_ti) +
578  null_check_suffix,
579  {lhs_lvs.front(),
580  rhs_lvs.front(),
581  lhs_ti.get_type() == kFLOAT ? cgen_state_->llFp(NULL_FLOAT)
584  }
585  CHECK(false);
586  return nullptr;
587 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
#define NULL_DOUBLE
std::string icmp_name(const SQLOps op_type)
Definition: CompareIR.cpp:45
#define IS_EQUIVALENCE(X)
Definition: sqldefs.h:72
CgenState * cgen_state_
#define NULL_FLOAT
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
void unpack_dict_encoded_string(CgenState *cgen_state, Executor *executor, SQLTypeInfo const ti, llvm::StructType *string_view_struct_type, std::vector< llvm::Value * > &lvs)
Definition: CompareIR.cpp:466
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::CmpInst::Predicate llvm_fcmp_pred(const SQLOps op_type)
Definition: CompareIR.cpp:83
bool is_time() const
Definition: sqltypes.h:579
bool is_integer() const
Definition: sqltypes.h:567
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool is_timeinterval() const
Definition: sqltypes.h:594
Executor * executor_
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
bool is_boolean() const
Definition: sqltypes.h:582
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1661
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
void unpack_none_encoded_string(CgenState *cgen_state, std::vector< llvm::Value * > &lvs)
Definition: CompareIR.cpp:456
Definition: sqldefs.h:74
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
llvm::Value * codegenQualifierCmp(const SQLOps, const SQLQualifier, std::vector< llvm::Value * >, const Analyzer::Expr *, const CompilationOptions &)
Definition: CompareIR.cpp:589
Definition: sqldefs.h:34
llvm::StructType * createStringViewStructType()
llvm::CmpInst::Predicate llvm_icmp_pred(const SQLOps op_type)
Definition: CompareIR.cpp:26
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool is_geometry() const
Definition: sqltypes.h:597
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
bool is_string() const
Definition: sqltypes.h:561
bool is_decimal() const
Definition: sqltypes.h:570
std::string string_cmp_func(const SQLOps optype)
Definition: CompareIR.cpp:106
#define IS_COMPARISON(X)
Definition: sqldefs.h:61

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegenCmpDecimalConst ( const SQLOps  optype,
const SQLQualifier  qualifier,
const Analyzer::Expr lhs,
const SQLTypeInfo lhs_ti,
const Analyzer::Expr rhs,
const CompilationOptions co 
)
private

Definition at line 402 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, Datum::bigintval, cgen_state_, codegen(), codegenCast(), codegenCmp(), exp_to_scale(), SQLTypeInfo::get_scale(), Analyzer::Expr::get_type_info(), kCAST, kDECIMAL, and sql_constants::kMaxRepresentableNumericPrecision.

Referenced by codegenCmp().

407  {
409  auto u_oper = dynamic_cast<const Analyzer::UOper*>(lhs);
410  if (!u_oper || u_oper->get_optype() != kCAST) {
411  return nullptr;
412  }
413  auto rhs_constant = dynamic_cast<const Analyzer::Constant*>(rhs);
414  if (!rhs_constant) {
415  return nullptr;
416  }
417  const auto operand = u_oper->get_operand();
418  const auto& operand_ti = operand->get_type_info();
419  if (operand_ti.is_decimal() && operand_ti.get_scale() < lhs_ti.get_scale()) {
420  // lhs decimal type has smaller scale
421  } else if (operand_ti.is_integer() && 0 < lhs_ti.get_scale()) {
422  // lhs is integer, no need to scale it all the way up to the cmp expr scale
423  } else {
424  return nullptr;
425  }
426 
427  auto scale_diff = lhs_ti.get_scale() - operand_ti.get_scale() - 1;
428  int64_t bigintval = rhs_constant->get_constval().bigintval;
429  bool negative = false;
430  if (bigintval < 0) {
431  negative = true;
432  bigintval = -bigintval;
433  }
434  int64_t truncated_decimal = bigintval / exp_to_scale(scale_diff);
435  int64_t decimal_tail = bigintval % exp_to_scale(scale_diff);
436  if (truncated_decimal % 10 == 0 && decimal_tail > 0) {
437  truncated_decimal += 1;
438  }
441  lhs_ti.get_scale() - scale_diff,
442  operand_ti.get_notnull());
443  if (negative) {
444  truncated_decimal = -truncated_decimal;
445  }
446  Datum d;
447  d.bigintval = truncated_decimal;
448  const auto new_rhs_lit =
449  makeExpr<Analyzer::Constant>(new_ti, rhs_constant->get_is_null(), d);
450  const auto operand_lv = codegen(operand, true, co).front();
451  const auto lhs_lv = codegenCast(operand_lv, operand_ti, new_ti, false, co);
452  return codegenCmp(optype, qualifier, {lhs_lv}, new_ti, new_rhs_lit.get(), co);
453 }
static constexpr int32_t kMaxRepresentableNumericPrecision
Definition: sqltypes.h:60
CgenState * cgen_state_
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
Definition: sqldefs.h:51
int64_t bigintval
Definition: Datum.h:76
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:230
uint64_t exp_to_scale(const unsigned exp)
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
Definition: Datum.h:71

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenColumn ( const Analyzer::ColumnVar col_var,
const bool  fetch_column,
const CompilationOptions co 
)
privatevirtual

Reimplemented in ScalarCodeGenerator.

Definition at line 94 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenColVar(), codegenOuterJoinNullPlaceholder(), foundOuterJoinMatch(), Analyzer::ColumnVar::get_rte_idx(), and CgenState::outer_join_match_found_per_level_.

Referenced by codegen().

96  {
98  if (col_var->get_rte_idx() <= 0 ||
100  !foundOuterJoinMatch(col_var->get_rte_idx())) {
101  return codegenColVar(col_var, fetch_column, true, co);
102  }
103  return codegenOuterJoinNullPlaceholder(col_var, fetch_column, co);
104 }
std::vector< llvm::Value * > outer_join_match_found_per_level_
Definition: CgenState.h:395
CgenState * cgen_state_
std::vector< llvm::Value * > codegenOuterJoinNullPlaceholder(const Analyzer::ColumnVar *col_var, const bool fetch_column, const CompilationOptions &co)
Definition: ColumnIR.cpp:496
llvm::Value * foundOuterJoinMatch(const size_t nesting_level) const
Definition: ColumnIR.cpp:489
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegenColVar(const Analyzer::ColumnVar *, const bool fetch_column, const bool update_query_plan, const CompilationOptions &)
Definition: ColumnIR.cpp:106
int32_t get_rte_idx() const
Definition: Analyzer.h:202

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenColVar ( const Analyzer::ColumnVar col_var,
const bool  fetch_column,
const bool  update_query_plan,
const CompilationOptions co 
)
private

Definition at line 106 of file ColumnIR.cpp.

References PlanState::addColumnToFetch(), PlanState::addColumnToNotFetch(), anonymous_namespace{ColumnIR.cpp}::adjusted_range_table_index(), AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_LT, codegen(), codegenFixedLengthColVar(), codegenFixedLengthColVarInWindow(), codegenRowId(), codegenVariableLengthStringColVar(), codegenWindowPosition(), colByteStream(), executor(), CgenState::fetch_cache_, CgenState::frag_offsets_, get_column_descriptor(), Analyzer::Expr::get_type_info(), WindowProjectNodeContext::getActiveWindowFunctionContext(), Analyzer::ColumnVar::getColumnKey(), hash_value(), hashJoinLhs(), CompilationOptions::hoist_literals, CgenState::ir_builder_, PlanState::isColumnToFetch(), PlanState::isLazyFetchColumn(), kENCODING_NONE, kPOINT, plan_state_, posArg(), resolveGroupedColumnReference(), and Analyzer::ColumnVar::toString().

Referenced by codegenColumn(), and codegenOuterJoinNullPlaceholder().

109  {
111  const bool hoist_literals = co.hoist_literals;
112  const int rte_idx = adjusted_range_table_index(col_var);
113  CHECK_LT(static_cast<size_t>(rte_idx), cgen_state_->frag_offsets_.size());
114  const auto& column_key = col_var->getColumnKey();
115  if (column_key.table_id > 0) {
116  const auto cd = get_column_descriptor(column_key);
117  if (cd->isVirtualCol) {
118  CHECK(cd->columnName == "rowid");
119  return {codegenRowId(col_var, co)};
120  }
121  const auto col_ti = cd->columnType;
122  if (col_ti.usesFlatBuffer()) {
123  throw std::runtime_error(
124  "Flatbuffer storage in a real table column not supported yet");
125  }
126  if (col_ti.get_physical_coord_cols() > 0) {
127  std::vector<llvm::Value*> cols;
128  const auto col_id = column_key.column_id;
129  auto temp_column_key = column_key;
130  bool fetch_physical_columns = fetch_column;
131  for (auto i = 0; i < col_ti.get_physical_coord_cols(); i++) {
132  temp_column_key.column_id = col_id + i + 1;
133  const auto cd0 = get_column_descriptor(temp_column_key);
134  CHECK(cd0);
135  const auto col0_ti = cd0->columnType;
136  CHECK(!cd0->isVirtualCol);
137  const auto col0_var =
138  makeExpr<Analyzer::ColumnVar>(col0_ti, temp_column_key, rte_idx);
139  if (plan_state_->isColumnToFetch(temp_column_key)) {
140  // sync the fetch status for all physical columns
141  fetch_physical_columns = true;
142  }
143  const auto col = codegenColVar(col0_var.get(), fetch_physical_columns, false, co);
144  cols.insert(cols.end(), col.begin(), col.end());
145  if (!fetch_physical_columns && plan_state_->isLazyFetchColumn(col_var)) {
146  plan_state_->addColumnToNotFetch(temp_column_key);
147  }
148  }
149  if (!fetch_physical_columns && plan_state_->isLazyFetchColumn(col_var)) {
150  plan_state_->addColumnToNotFetch(column_key);
151  } else {
152  plan_state_->addColumnToFetch(column_key);
153  }
154  return cols;
155  }
156  }
157  const auto grouped_col_lv = resolveGroupedColumnReference(col_var);
158  if (grouped_col_lv) {
159  return {grouped_col_lv};
160  }
161  const auto col_var_hash = boost::hash_value(col_var->toString());
162  const auto window_func_context =
164  // only generate the decoding code once; if a column has been previously
165  // fetched in the generated IR, we'll reuse it
166  // here, we do not just use (local) column id since our analyzer may cast the same
167  // col_var with different types depending on the (aggregate) function that the col_var
168  // is used i.e., SELECT COUNT(DISTINCT x), MIN(x) FROM ...
169  if (!window_func_context) {
170  auto it = cgen_state_->fetch_cache_.find(col_var_hash);
171  if (it != cgen_state_->fetch_cache_.end()) {
172  return {it->second};
173  }
174  }
175  const auto hash_join_lhs = hashJoinLhs(col_var);
176  // Note(jclay): This has been prone to cause failures in some bounding box intersection.
177  // I believe most of the issues are worked out now, but a good place to check if
178  // failures are happening.
179 
180  // Use the already fetched left-hand side of an equi-join if the types are identical.
181  // Currently, types can only be different because of different underlying dictionaries.
182  if (hash_join_lhs && hash_join_lhs->get_type_info() == col_var->get_type_info()) {
183  if (plan_state_->isLazyFetchColumn(col_var)) {
184  plan_state_->addColumnToFetch(col_var->getColumnKey(), true);
185  }
186  return codegen(hash_join_lhs.get(), fetch_column, co);
187  }
188  auto pos_arg = posArg(col_var);
189  if (window_func_context) {
190  pos_arg = codegenWindowPosition(window_func_context, pos_arg);
191  }
192  auto col_byte_stream = colByteStream(col_var, fetch_column, hoist_literals);
193  if (plan_state_->isLazyFetchColumn(col_var)) {
194  if (update_query_plan) {
196  }
197  if (rte_idx > 0) {
198  const auto offset = cgen_state_->frag_offsets_[rte_idx];
199  if (offset) {
200  return {cgen_state_->ir_builder_.CreateAdd(pos_arg, offset)};
201  } else {
202  return {pos_arg};
203  }
204  }
205  return {pos_arg};
206  }
207  const auto& col_ti = col_var->get_type_info();
208  if (col_ti.is_string() && col_ti.get_compression() == kENCODING_NONE) {
209  const auto varlen_str_column_lvs =
210  codegenVariableLengthStringColVar(col_byte_stream, pos_arg);
211  if (!window_func_context) {
212  auto it_ok = cgen_state_->fetch_cache_.insert(
213  std::make_pair(col_var_hash, varlen_str_column_lvs));
214  CHECK(it_ok.second);
215  }
216  return varlen_str_column_lvs;
217  }
218  if (col_ti.usesFlatBuffer()) {
219  return {col_byte_stream};
220  }
221  if (col_ti.is_array() || col_ti.get_type() == kPOINT) {
222  return {col_byte_stream};
223  }
224  if (window_func_context) {
226  col_var, col_byte_stream, pos_arg, co, window_func_context)};
227  }
228  const auto fixed_length_column_lv =
229  codegenFixedLengthColVar(col_var, col_byte_stream, pos_arg);
230  auto it_ok = cgen_state_->fetch_cache_.insert(
231  std::make_pair(col_var_hash, std::vector<llvm::Value*>{fixed_length_column_lv}));
232  return {it_ok.first->second};
233 }
std::unordered_map< size_t, std::vector< llvm::Value * > > fetch_cache_
Definition: CgenState.h:385
CgenState * cgen_state_
llvm::Value * codegenRowId(const Analyzer::ColumnVar *col_var, const CompilationOptions &co)
Definition: ColumnIR.cpp:391
void addColumnToFetch(const shared::ColumnKey &column_key, bool unmark_lazy_fetch=false)
Definition: PlanState.cpp:124
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
static WindowFunctionContext * getActiveWindowFunctionContext(Executor *executor)
void addColumnToNotFetch(const shared::ColumnKey &column_key)
Definition: PlanState.cpp:147
std::shared_ptr< const Analyzer::Expr > hashJoinLhs(const Analyzer::ColumnVar *rhs) const
Definition: ColumnIR.cpp:630
llvm::Value * codegenWindowPosition(const WindowFunctionContext *window_func_context, llvm::Value *pos_arg)
Definition: ColumnIR.cpp:235
bool isColumnToFetch(const shared::ColumnKey &column_key) const
Definition: PlanState.cpp:114
bool isLazyFetchColumn(const Analyzer::Expr *target_expr) const
Definition: PlanState.cpp:22
std::string toString() const override
Definition: Analyzer.cpp:2717
const ColumnDescriptor * get_column_descriptor(const shared::ColumnKey &column_key)
Definition: Execute.h:213
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegenColVar(const Analyzer::ColumnVar *, const bool fetch_column, const bool update_query_plan, const CompilationOptions &)
Definition: ColumnIR.cpp:106
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
PlanState * plan_state_
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
#define CHECK_LT(x, y)
Definition: Logger.h:303
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
std::vector< llvm::Value * > frag_offsets_
Definition: CgenState.h:393
llvm::Value * codegenFixedLengthColVarInWindow(const Analyzer::ColumnVar *col_var, llvm::Value *col_byte_stream, llvm::Value *pos_arg, const CompilationOptions &co, const WindowFunctionContext *window_function_context=nullptr)
Definition: ColumnIR.cpp:299
std::size_t hash_value(RexAbstractInput const &rex_ab_input)
Definition: RelAlgDag.cpp:3548
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * colByteStream(const Analyzer::ColumnVar *col_var, const bool fetch_column, const bool hoist_literals)
Definition: ColumnIR.cpp:574
llvm::Value * codegenFixedLengthColVar(const Analyzer::ColumnVar *col_var, llvm::Value *col_byte_stream, llvm::Value *pos_arg, const WindowFunctionContext *window_function_context=nullptr)
Definition: ColumnIR.cpp:248
std::vector< llvm::Value * > codegenVariableLengthStringColVar(llvm::Value *col_byte_stream, llvm::Value *pos_arg)
Definition: ColumnIR.cpp:377
int adjusted_range_table_index(const Analyzer::ColumnVar *col_var)
Definition: ColumnIR.cpp:88
llvm::Value * resolveGroupedColumnReference(const Analyzer::ColumnVar *)
Definition: ColumnIR.cpp:554
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenCompression ( const SQLTypeInfo type_info)
private

Definition at line 675 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, SQLTypeInfo::get_comp_param(), SQLTypeInfo::get_compression(), kENCODING_GEOINT, and CgenState::llInt().

Referenced by codegenFunctionOperCastArgs().

675  {
677  int32_t compression = (type_info.get_compression() == kENCODING_GEOINT &&
678  type_info.get_comp_param() == 32)
679  ? 1
680  : 0;
681 
682  return cgen_state_->llInt(compression);
683 }
CgenState * cgen_state_
#define AUTOMATIC_IR_METADATA(CGENSTATE)
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:402
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenConstantWidthBucketExpr ( const Analyzer::WidthBucketExpr expr,
const CompilationOptions co 
)
private

Definition at line 364 of file IRCodegen.cpp.

References Analyzer::WidthBucketExpr::can_skip_out_of_bound_check(), cgen_state_, CHECK_EQ, codegen(), Datum::doubleval, CgenState::emitCall(), Analyzer::WidthBucketExpr::get_bound_val(), Analyzer::WidthBucketExpr::get_lower_bound(), Analyzer::WidthBucketExpr::get_partition_count(), Analyzer::WidthBucketExpr::get_partition_count_val(), Analyzer::WidthBucketExpr::get_target_value(), Analyzer::WidthBucketExpr::get_upper_bound(), inline_fp_null_val(), inline_int_null_val(), kDOUBLE, and NULL_DOUBLE.

Referenced by codegen().

366  {
367  auto target_value_expr = expr->get_target_value();
368  auto lower_bound_expr = expr->get_lower_bound();
369  auto upper_bound_expr = expr->get_upper_bound();
370  auto partition_count_expr = expr->get_partition_count();
371 
372  auto num_partitions = expr->get_partition_count_val();
373  if (num_partitions < 1 || num_partitions > INT32_MAX) {
374  throw std::runtime_error(
375  "PARTITION_COUNT expression of width_bucket function should be in a valid "
376  "range: 0 < PARTITION_COUNT <= 2147483647");
377  }
378  double lower = expr->get_bound_val(lower_bound_expr);
379  double upper = expr->get_bound_val(upper_bound_expr);
380  if (lower == upper) {
381  throw std::runtime_error(
382  "LOWER_BOUND and UPPER_BOUND expressions of width_bucket function cannot have "
383  "the same constant value");
384  }
385  if (lower == NULL_DOUBLE || upper == NULL_DOUBLE) {
386  throw std::runtime_error(
387  "Both LOWER_BOUND and UPPER_BOUND of width_bucket function should be finite "
388  "numeric constants.");
389  }
390 
391  bool const reversed = lower > upper;
392  double const scale_factor = num_partitions / (reversed ? lower - upper : upper - lower);
393  std::string func_name = reversed ? "width_bucket_reversed" : "width_bucket";
394 
395  auto get_double_constant_lvs = [this, &co](double const_val) {
396  Datum d;
397  d.doubleval = const_val;
398  auto double_const_expr =
399  makeExpr<Analyzer::Constant>(SQLTypeInfo(kDOUBLE, false), false, d);
400  return codegen(double_const_expr.get(), false, co);
401  };
402 
403  auto target_value_ti = target_value_expr->get_type_info();
404  auto target_value_expr_lvs = codegen(target_value_expr, true, co);
405  CHECK_EQ(size_t(1), target_value_expr_lvs.size());
406  auto lower_expr_lvs = codegen(lower_bound_expr, true, co);
407  CHECK_EQ(size_t(1), lower_expr_lvs.size());
408  auto scale_factor_lvs = get_double_constant_lvs(scale_factor);
409  CHECK_EQ(size_t(1), scale_factor_lvs.size());
410 
411  std::vector<llvm::Value*> width_bucket_args{target_value_expr_lvs[0],
412  lower_expr_lvs[0]};
413  if (expr->can_skip_out_of_bound_check()) {
414  func_name += "_no_oob_check";
415  width_bucket_args.push_back(scale_factor_lvs[0]);
416  } else {
417  auto upper_expr_lvs = codegen(upper_bound_expr, true, co);
418  CHECK_EQ(size_t(1), upper_expr_lvs.size());
419  auto partition_count_expr_lvs = codegen(partition_count_expr, true, co);
420  CHECK_EQ(size_t(1), partition_count_expr_lvs.size());
421  width_bucket_args.push_back(upper_expr_lvs[0]);
422  width_bucket_args.push_back(scale_factor_lvs[0]);
423  width_bucket_args.push_back(partition_count_expr_lvs[0]);
424  if (!target_value_ti.get_notnull()) {
425  func_name += "_nullable";
426  auto translated_null_value = target_value_ti.is_fp()
427  ? inline_fp_null_val(target_value_ti)
428  : inline_int_null_val(target_value_ti);
429  auto null_value_lvs = get_double_constant_lvs(translated_null_value);
430  CHECK_EQ(size_t(1), null_value_lvs.size());
431  width_bucket_args.push_back(null_value_lvs[0]);
432  }
433  }
434  return cgen_state_->emitCall(func_name, width_bucket_args);
435 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Expr * get_partition_count() const
Definition: Analyzer.h:1201
#define NULL_DOUBLE
CgenState * cgen_state_
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
double get_bound_val(const Analyzer::Expr *bound_expr) const
Definition: Analyzer.cpp:3936
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
int32_t get_partition_count_val() const
Definition: Analyzer.cpp:3946
const Expr * get_target_value() const
Definition: Analyzer.h:1198
bool can_skip_out_of_bound_check() const
Definition: Analyzer.h:1243
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
const Expr * get_lower_bound() const
Definition: Analyzer.h:1199
const Expr * get_upper_bound() const
Definition: Analyzer.h:1200
Definition: Datum.h:71
double doubleval
Definition: Datum.h:78

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenDateTruncHighPrecisionTimestamps ( llvm::Value *  ts_lv,
const SQLTypeInfo ti,
const DatetruncField field 
)
private

Definition at line 304 of file DateTimeIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, datetrunc_fname_lookup, dtMICROSECOND, dtMILLISECOND, dtNANOSECOND, dtSECOND, CgenState::emitCall(), CgenState::emitExternalCall(), executor(), SQLTypeInfo::get_dimension(), get_int_type(), SQLTypeInfo::get_notnull(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_high_precision_timestamp(), and CgenState::llInt().

Referenced by codegen().

307  {
308  // Only needed for i in { 0, 3, 6, 9 }.
309  constexpr int64_t pow10[10]{1, 0, 0, 1000, 0, 0, 1000000, 0, 0, 1000000000};
312  CHECK(ts_lv->getType()->isIntegerTy(64));
313  bool const is_nullable = !ti.get_notnull();
314  static_assert(dtSECOND + 1 == dtMILLISECOND, "Please keep these consecutive.");
315  static_assert(dtMILLISECOND + 1 == dtMICROSECOND, "Please keep these consecutive.");
316  static_assert(dtMICROSECOND + 1 == dtNANOSECOND, "Please keep these consecutive.");
317  if (dtSECOND <= field && field <= dtNANOSECOND) {
318  unsigned const start_dim = ti.get_dimension(); // 0, 3, 6, 9
319  unsigned const trunc_dim = (field - dtSECOND) * 3; // 0, 3, 6, 9
320  if (start_dim <= trunc_dim) {
321  return ts_lv; // Truncating to an equal or higher precision has no effect.
322  }
323  int64_t const dscale = pow10[start_dim - trunc_dim]; // 1e3, 1e6, 1e9
324  if (is_nullable) {
325  ts_lv = cgen_state_->emitCall(
326  "floor_div_nullable_lhs",
327  {ts_lv, cgen_state_->llInt(dscale), cgen_state_->inlineIntNull(ti)});
328  return cgen_state_->emitCall(
329  "mul_int64_t_nullable_lhs",
330  {ts_lv, cgen_state_->llInt(dscale), cgen_state_->inlineIntNull(ti)});
331  } else {
332  ts_lv = cgen_state_->ir_builder_.CreateSDiv(ts_lv, cgen_state_->llInt(dscale));
333  return cgen_state_->ir_builder_.CreateMul(ts_lv, cgen_state_->llInt(dscale));
334  }
335  }
336  int64_t const scale = pow10[ti.get_dimension()];
337  ts_lv = is_nullable
339  "floor_div_nullable_lhs",
340  {ts_lv, cgen_state_->llInt(scale), cgen_state_->inlineIntNull(ti)})
341  : cgen_state_->ir_builder_.CreateSDiv(ts_lv, cgen_state_->llInt(scale));
342 
343  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
344  if (is_nullable) {
345  nullcheck_codegen = std::make_unique<NullCheckCodegen>(
346  cgen_state_, executor(), ts_lv, ti, "date_trunc_hp_nullcheck");
347  }
348  char const* const fname = datetrunc_fname_lookup.at(field);
349  ts_lv = cgen_state_->emitExternalCall(
350  fname, get_int_type(64, cgen_state_->context_), {ts_lv});
351  if (is_nullable) {
352  ts_lv =
353  nullcheck_codegen->finalize(ll_int(NULL_BIGINT, cgen_state_->context_), ts_lv);
354  }
355 
356  return is_nullable
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));
361 }
CgenState * cgen_state_
#define NULL_BIGINT
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
constexpr std::array< char const *, dtINVALID > datetrunc_fname_lookup
Definition: DateTruncate.h:49
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool is_high_precision_timestamp() const
Definition: sqltypes.h:1036
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenDeciDiv ( const Analyzer::BinOper bin_oper,
const CompilationOptions co 
)
private

Definition at line 546 of file ArithmeticIR.cpp.

References Parser::IntLiteral::analyzeValue(), AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), codegenCastBetweenIntTypes(), codegenDiv(), codegenIntConst(), exp_to_scale(), Analyzer::BinOper::get_left_operand(), get_null_check_suffix(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), kCAST, and anonymous_namespace{ArithmeticIR.cpp}::numeric_or_time_interval_type_name().

Referenced by codegenArith().

547  {
549  auto lhs = bin_oper->get_left_operand();
550  auto rhs = bin_oper->get_right_operand();
551  const auto& lhs_type = lhs->get_type_info();
552  const auto& rhs_type = rhs->get_type_info();
553  CHECK(lhs_type.is_decimal() && rhs_type.is_decimal() &&
554  lhs_type.get_scale() == rhs_type.get_scale());
555 
556  auto rhs_constant = dynamic_cast<const Analyzer::Constant*>(rhs);
557  auto rhs_cast = dynamic_cast<const Analyzer::UOper*>(rhs);
558  if (rhs_constant && !rhs_constant->get_is_null() &&
559  rhs_constant->get_constval().bigintval != 0LL &&
560  (rhs_constant->get_constval().bigintval % exp_to_scale(rhs_type.get_scale())) ==
561  0LL) {
562  // can safely downscale a scaled constant
563  } else if (rhs_cast && rhs_cast->get_optype() == kCAST &&
564  rhs_cast->get_operand()->get_type_info().is_integer()) {
565  // can skip upscale in the int to dec cast
566  } else {
567  return nullptr;
568  }
569 
570  auto lhs_lv = codegen(lhs, true, co).front();
571  llvm::Value* rhs_lv{nullptr};
572  if (rhs_constant) {
573  const auto rhs_lit = Parser::IntLiteral::analyzeValue(
574  rhs_constant->get_constval().bigintval / exp_to_scale(rhs_type.get_scale()));
575  auto rhs_lit_lv = CodeGenerator::codegenIntConst(
576  dynamic_cast<const Analyzer::Constant*>(rhs_lit.get()), cgen_state_);
578  rhs_lit_lv, rhs_lit->get_type_info(), lhs_type, /*upscale*/ false);
579  } else if (rhs_cast) {
580  auto rhs_cast_oper = rhs_cast->get_operand();
581  const auto& rhs_cast_oper_ti = rhs_cast_oper->get_type_info();
582  auto rhs_cast_oper_lv = codegen(rhs_cast_oper, true, co).front();
584  rhs_cast_oper_lv, rhs_cast_oper_ti, lhs_type, /*upscale*/ false);
585  } else {
586  CHECK(false);
587  }
588  const auto int_typename = numeric_or_time_interval_type_name(lhs_type, rhs_type);
589  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
590  return codegenDiv(lhs_lv,
591  rhs_lv,
592  null_check_suffix.empty() ? "" : int_typename,
593  null_check_suffix,
594  lhs_type,
595  /*upscale*/ false);
596 }
CgenState * cgen_state_
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:166
const Expr * get_right_operand() const
Definition: Analyzer.h:456
Definition: sqldefs.h:51
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)
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:427
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1661
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
static llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant, CgenState *cgen_state)
Definition: ConstantIR.cpp:89
#define CHECK(condition)
Definition: Logger.h:291
uint64_t exp_to_scale(const unsigned exp)
const Expr * get_left_operand() const
Definition: Analyzer.h:455

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenDictLike ( const std::shared_ptr< Analyzer::Expr arg,
const Analyzer::Constant pattern,
const bool  ilike,
const bool  is_simple,
const char  escape_char,
const CompilationOptions co 
)
private

Definition at line 671 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), executor(), Analyzer::Constant::get_constval(), Analyzer::Expr::get_type_info(), kCAST, kENCODING_DICT, kENCODING_NONE, pre_translate_string_ops(), Datum::stringval, timer_start(), timer_stop(), and VLOG.

Referenced by codegen().

677  {
679  const auto cast_oper = std::dynamic_pointer_cast<Analyzer::UOper>(like_arg);
680  if (!cast_oper) {
681  return nullptr;
682  }
683  CHECK(cast_oper);
684  CHECK_EQ(kCAST, cast_oper->get_optype());
685  const auto dict_like_arg = cast_oper->get_own_operand();
686  const auto& dict_like_arg_ti = dict_like_arg->get_type_info();
687  if (!dict_like_arg_ti.is_string()) {
688  throw(std::runtime_error("Cast from " + dict_like_arg_ti.get_type_name() + " to " +
689  cast_oper->get_type_info().get_type_name() +
690  " not supported"));
691  }
692  CHECK_EQ(kENCODING_DICT, dict_like_arg_ti.get_compression());
693  const auto sdp = executor()->getStringDictionaryProxy(
694  dict_like_arg_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true);
695  if (sdp->storageEntryCount() > 200000000) {
696  return nullptr;
697  }
698  if (sdp->getDictKey().isTransientDict()) {
699  // If we have a literal dictionary it was a product
700  // of string ops applied to none-encoded strings, and
701  // will not be populated at codegen-time, so we
702  // cannot use the fast path
703 
704  // Todo(todd): Once string ops support non-string producting
705  // operators (like like/ilike), like/ilike can be chained and
706  // we can avoid the string translation
707  return nullptr;
708  }
709  const auto string_oper = dynamic_cast<const Analyzer::StringOper*>(dict_like_arg.get());
710  if (string_oper) {
711  pre_translate_string_ops(string_oper, executor());
712  }
713  const auto& pattern_ti = pattern->get_type_info();
714  CHECK(pattern_ti.is_string());
715  CHECK_EQ(kENCODING_NONE, pattern_ti.get_compression());
716  const auto& pattern_datum = pattern->get_constval();
717  const auto& pattern_str = *pattern_datum.stringval;
718  auto work_timer = timer_start();
719  const auto matching_ids =
720  sdp->getLike<int64_t>(pattern_str, ilike, is_simple, escape_char);
721  auto const work_ms = timer_stop(work_timer);
722  VLOG(3) << "Processing like operator with the pattern " << pattern_str << " took "
723  << work_ms << " ms (# matching elems: " << matching_ids.size() << ")";
724  const auto in_values = std::make_shared<Analyzer::InIntegerSet>(
725  dict_like_arg, matching_ids, dict_like_arg_ti.get_notnull());
726  return codegen(in_values.get(), co);
727 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
void pre_translate_string_ops(const Analyzer::StringOper *string_oper, Executor *executor)
TypeR::rep timer_stop(Type clock_begin)
Definition: measure.h:48
Definition: sqldefs.h:51
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::string * stringval
Definition: Datum.h:81
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Expression class for string functions The &quot;arg&quot; constructor parameter must be an expression that reso...
Definition: Analyzer.h:1601
Datum get_constval() const
Definition: Analyzer.h:348
#define CHECK(condition)
Definition: Logger.h:291
#define VLOG(n)
Definition: Logger.h:388
Type timer_start()
Definition: measure.h:42
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenDictRegexp ( const std::shared_ptr< Analyzer::Expr arg,
const Analyzer::Constant pattern,
const char  escape_char,
const CompilationOptions co 
)
private

Definition at line 903 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), gpu_enabled::copy(), executor(), Analyzer::Constant::get_constval(), Analyzer::Expr::get_type_info(), kCAST, kENCODING_DICT, kENCODING_NONE, pre_translate_string_ops(), and Datum::stringval.

Referenced by codegen().

907  {
909  const auto cast_oper = std::dynamic_pointer_cast<Analyzer::UOper>(pattern_arg);
910  if (!cast_oper) {
911  return nullptr;
912  }
913  CHECK(cast_oper);
914  CHECK_EQ(kCAST, cast_oper->get_optype());
915  const auto dict_regexp_arg = cast_oper->get_own_operand();
916  const auto& dict_regexp_arg_ti = dict_regexp_arg->get_type_info();
917  CHECK(dict_regexp_arg_ti.is_string());
918  CHECK_EQ(kENCODING_DICT, dict_regexp_arg_ti.get_compression());
919  const auto& dict_key = dict_regexp_arg_ti.getStringDictKey();
920  const auto sdp = executor()->getStringDictionaryProxy(
921  dict_key, executor()->getRowSetMemoryOwner(), true);
922  if (sdp->storageEntryCount() > 15000000) {
923  return nullptr;
924  }
925  if (sdp->getDictKey().isTransientDict()) {
926  // If we have a literal dictionary it was a product
927  // of string ops applied to none-encoded strings, and
928  // will not be populated at codegen-time, so we
929  // cannot use the fast path
930 
931  // Todo(todd): Once string ops support non-string producting
932  // operators (like regexp_like), these operators can be chained
933  // and we can avoid the string translation
934  return nullptr;
935  }
936  const auto string_oper =
937  dynamic_cast<const Analyzer::StringOper*>(dict_regexp_arg.get());
938  if (string_oper) {
939  pre_translate_string_ops(string_oper, executor());
940  }
941  const auto& pattern_ti = pattern->get_type_info();
942  CHECK(pattern_ti.is_string());
943  CHECK_EQ(kENCODING_NONE, pattern_ti.get_compression());
944  const auto& pattern_datum = pattern->get_constval();
945  const auto& pattern_str = *pattern_datum.stringval;
946  const auto matching_ids = sdp->getRegexpLike(pattern_str, escape_char);
947  // InIntegerSet requires 64-bit values
948  std::vector<int64_t> matching_ids_64(matching_ids.size());
949  std::copy(matching_ids.begin(), matching_ids.end(), matching_ids_64.begin());
950  const auto in_values = std::make_shared<Analyzer::InIntegerSet>(
951  dict_regexp_arg, matching_ids_64, dict_regexp_arg_ti.get_notnull());
952  return codegen(in_values.get(), co);
953 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
void pre_translate_string_ops(const Analyzer::StringOper *string_oper, Executor *executor)
Definition: sqldefs.h:51
DEVICE auto copy(ARGS &&...args)
Definition: gpu_enabled.h:51
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::string * stringval
Definition: Datum.h:81
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Expression class for string functions The &quot;arg&quot; constructor parameter must be an expression that reso...
Definition: Analyzer.h:1601
Datum get_constval() const
Definition: Analyzer.h:348
#define CHECK(condition)
Definition: Logger.h:291
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenDictStrCmp ( const std::shared_ptr< Analyzer::Expr lhs,
const std::shared_ptr< Analyzer::Expr rhs,
const SQLOps  compare_operator,
const CompilationOptions co 
)
private

Definition at line 762 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), gpu_enabled::copy(), executor(), anonymous_namespace{StringOpsIR.cpp}::get_compared_ids(), Analyzer::Constant::get_constval(), kCAST, kENCODING_DICT, kEQ, kGE, kGT, kLE, kLT, and kNE.

Referenced by codegenStrCmp().

765  {
767  auto rhs_cast_oper = std::dynamic_pointer_cast<const Analyzer::UOper>(rhs);
768  auto lhs_cast_oper = std::dynamic_pointer_cast<const Analyzer::UOper>(lhs);
769  auto rhs_col_var = std::dynamic_pointer_cast<const Analyzer::ColumnVar>(rhs);
770  auto lhs_col_var = std::dynamic_pointer_cast<const Analyzer::ColumnVar>(lhs);
771  std::shared_ptr<const Analyzer::UOper> cast_oper;
772  std::shared_ptr<const Analyzer::ColumnVar> col_var;
773  auto compare_opr = compare_operator;
774  if (lhs_col_var && rhs_col_var) {
775  if (lhs_col_var->get_type_info().getStringDictKey() ==
776  rhs_col_var->get_type_info().getStringDictKey()) {
777  if (compare_operator == kEQ || compare_operator == kNE) {
778  // TODO (vraj): implement compare between two dictionary encoded columns which
779  // share a dictionary
780  return nullptr;
781  }
782  }
783  // TODO (vraj): implement compare between two dictionary encoded columns which don't
784  // shared dictionary
785  throw std::runtime_error("Decoding two Dictionary encoded columns will be slow");
786  } else if (lhs_col_var && rhs_cast_oper) {
787  cast_oper.swap(rhs_cast_oper);
788  col_var.swap(lhs_col_var);
789  } else if (lhs_cast_oper && rhs_col_var) {
790  cast_oper.swap(lhs_cast_oper);
791  col_var.swap(rhs_col_var);
792  switch (compare_operator) {
793  case kLT:
794  compare_opr = kGT;
795  break;
796  case kLE:
797  compare_opr = kGE;
798  break;
799  case kGT:
800  compare_opr = kLT;
801  break;
802  case kGE:
803  compare_opr = kLE;
804  default:
805  break;
806  }
807  }
808  if (!cast_oper || !col_var) {
809  return nullptr;
810  }
811  CHECK_EQ(kCAST, cast_oper->get_optype());
812 
813  const auto const_expr =
814  dynamic_cast<Analyzer::Constant*>(cast_oper->get_own_operand().get());
815  if (!const_expr) {
816  // Analyzer casts dictionary encoded columns to none encoded if there is a comparison
817  // between two encoded columns. Which we currently do not handle.
818  return nullptr;
819  }
820  const auto& const_val = const_expr->get_constval();
821 
822  const auto col_ti = col_var->get_type_info();
823  CHECK(col_ti.is_string());
824  CHECK_EQ(kENCODING_DICT, col_ti.get_compression());
825  const auto sdp = executor()->getStringDictionaryProxy(
826  col_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true);
827 
828  if (sdp->storageEntryCount() > 200000000) {
829  std::runtime_error("Cardinality for string dictionary is too high");
830  return nullptr;
831  }
832 
833  const auto& pattern_str = *const_val.stringval;
834  const auto matching_ids = get_compared_ids(sdp, compare_opr, pattern_str);
835 
836  // InIntegerSet requires 64-bit values
837  std::vector<int64_t> matching_ids_64(matching_ids.size());
838  std::copy(matching_ids.begin(), matching_ids.end(), matching_ids_64.begin());
839 
840  const auto in_values = std::make_shared<Analyzer::InIntegerSet>(
841  col_var, matching_ids_64, col_ti.get_notnull());
842  return codegen(in_values.get(), co);
843 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::vector< int32_t > get_compared_ids(const StringDictionaryProxy *dict, const SQLOps compare_operator, const std::string &pattern)
CgenState * cgen_state_
Definition: sqldefs.h:37
Definition: sqldefs.h:38
Definition: sqldefs.h:51
Definition: sqldefs.h:32
DEVICE auto copy(ARGS &&...args)
Definition: gpu_enabled.h:51
#define AUTOMATIC_IR_METADATA(CGENSTATE)
Definition: sqldefs.h:36
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Datum get_constval() const
Definition: Analyzer.h:348
Definition: sqldefs.h:34
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:35
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenDiv ( llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const std::string &  null_typename,
const std::string &  null_check_suffix,
const SQLTypeInfo ti,
bool  upscale = true 
)
private

Definition at line 433 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegenSkipOverflowCheckForNull(), CgenState::context_, CgenState::current_func_, CgenState::emitCall(), exp_to_scale(), g_null_div_by_zero, get_int_type(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_scale(), SQLTypeInfo::get_type(), inline_int_null_val(), CgenState::inlineIntMaxMin(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), SQLTypeInfo::is_fp(), kBOOLEAN, kFLOAT, CgenState::llFp(), CgenState::llInt(), CgenState::needs_error_check_, NULL_DOUBLE, NULL_FLOAT, numeric_type_name(), and toBool().

Referenced by codegenDeciDiv(), codegenFpArith(), and codegenIntArith().

438  {
440  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
441  if (ti.is_decimal()) {
442  if (upscale) {
443  CHECK(lhs_lv->getType()->isIntegerTy());
444  const auto scale_lv =
445  llvm::ConstantInt::get(lhs_lv->getType(), exp_to_scale(ti.get_scale()));
446 
447  lhs_lv = cgen_state_->ir_builder_.CreateSExt(
448  lhs_lv, get_int_type(64, cgen_state_->context_));
449  llvm::Value* chosen_max{nullptr};
450  llvm::Value* chosen_min{nullptr};
451  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(8, true);
452  auto decimal_div_ok = llvm::BasicBlock::Create(
453  cgen_state_->context_, "decimal_div_ok", cgen_state_->current_func_);
454  if (!null_check_suffix.empty()) {
455  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, decimal_div_ok, ti);
456  }
457  auto decimal_div_fail = llvm::BasicBlock::Create(
458  cgen_state_->context_, "decimal_div_fail", cgen_state_->current_func_);
459  auto lhs_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() /
460  exp_to_scale(ti.get_scale());
461  auto lhs_max_lv =
462  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), lhs_max);
463  llvm::Value* detected{nullptr};
464  if (ti.get_notnull()) {
465  detected = cgen_state_->ir_builder_.CreateICmpSGT(lhs_lv, lhs_max_lv);
466  } else {
467  detected = toBool(cgen_state_->emitCall(
468  "gt_" + numeric_type_name(ti) + "_nullable",
469  {lhs_lv,
470  lhs_max_lv,
473  }
474  cgen_state_->ir_builder_.CreateCondBr(detected, decimal_div_fail, decimal_div_ok);
475 
476  cgen_state_->ir_builder_.SetInsertPoint(decimal_div_fail);
477  cgen_state_->ir_builder_.CreateRet(
478  cgen_state_->llInt(int32_t(ErrorCode::OVERFLOW_OR_UNDERFLOW)));
479 
480  cgen_state_->ir_builder_.SetInsertPoint(decimal_div_ok);
481 
482  lhs_lv = null_typename.empty()
483  ? cgen_state_->ir_builder_.CreateMul(lhs_lv, scale_lv)
485  "mul_" + numeric_type_name(ti) + null_check_suffix,
486  {lhs_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(ti))});
487  }
488  }
489  if (g_null_div_by_zero) {
490  llvm::Value* null_lv{nullptr};
491  if (ti.is_fp()) {
492  null_lv = ti.get_type() == kFLOAT ? cgen_state_->llFp(NULL_FLOAT)
494  } else {
495  null_lv = cgen_state_->llInt(inline_int_null_val(ti));
496  }
497  return cgen_state_->emitCall("safe_div_" + numeric_type_name(ti),
498  {lhs_lv, rhs_lv, null_lv});
499  }
501  auto div_ok = llvm::BasicBlock::Create(
503  if (!null_check_suffix.empty()) {
504  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, div_ok, ti);
505  }
506  auto div_zero = llvm::BasicBlock::Create(
508  auto zero_const = rhs_lv->getType()->isIntegerTy()
509  ? llvm::ConstantInt::get(rhs_lv->getType(), 0, true)
510  : llvm::ConstantFP::get(rhs_lv->getType(), 0.);
511  cgen_state_->ir_builder_.CreateCondBr(
512  zero_const->getType()->isFloatingPointTy()
513  ? cgen_state_->ir_builder_.CreateFCmp(
514  llvm::FCmpInst::FCMP_ONE, rhs_lv, zero_const)
515  : cgen_state_->ir_builder_.CreateICmp(
516  llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
517  div_ok,
518  div_zero);
519  cgen_state_->ir_builder_.SetInsertPoint(div_ok);
520  auto ret =
521  zero_const->getType()->isIntegerTy()
522  ? (null_typename.empty()
523  ? cgen_state_->ir_builder_.CreateSDiv(lhs_lv, rhs_lv)
525  "div_" + null_typename + null_check_suffix,
526  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))}))
527  : (null_typename.empty()
528  ? cgen_state_->ir_builder_.CreateFDiv(lhs_lv, rhs_lv)
530  "div_" + null_typename + null_check_suffix,
531  {lhs_lv,
532  rhs_lv,
535  cgen_state_->ir_builder_.SetInsertPoint(div_zero);
536  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt(int32_t(ErrorCode::DIV_BY_ZERO)));
537  cgen_state_->ir_builder_.SetInsertPoint(div_ok);
538  return ret;
539 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define NULL_DOUBLE
CgenState * cgen_state_
#define NULL_FLOAT
bool is_fp() const
Definition: sqltypes.h:573
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool g_null_div_by_zero
Definition: Execute.cpp:95
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
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:65
bool needs_error_check_
Definition: CgenState.h:405
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
bool is_decimal() const
Definition: sqltypes.h:570
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenExtractHighPrecisionTimestamps ( llvm::Value *  ts_lv,
const SQLTypeInfo ti,
const ExtractField field 
)
private

Definition at line 260 of file DateTimeIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::emitCall(), SQLTypeInfo::get_dimension(), DateTimeUtils::get_extract_high_precision_adjusted_scale(), SQLTypeInfo::get_notnull(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_high_precision_timestamp(), DateTimeUtils::is_subsecond_extract_field(), kDIVIDE, kMULTIPLY, CgenState::llInt(), and run_benchmark_import::result.

263  {
266  CHECK(ts_lv->getType()->isIntegerTy(64));
268  const auto result =
270  if (result.first == kMULTIPLY) {
271  return ti.get_notnull()
272  ? cgen_state_->ir_builder_.CreateMul(
273  ts_lv, cgen_state_->llInt(static_cast<int64_t>(result.second)))
275  "mul_int64_t_nullable_lhs",
276  {ts_lv,
277  cgen_state_->llInt(static_cast<int64_t>(result.second)),
278  cgen_state_->inlineIntNull(ti)});
279  } else if (result.first == kDIVIDE) {
280  return ti.get_notnull()
281  ? cgen_state_->ir_builder_.CreateSDiv(
282  ts_lv, cgen_state_->llInt(static_cast<int64_t>(result.second)))
284  "floor_div_nullable_lhs",
285  {ts_lv,
286  cgen_state_->llInt(static_cast<int64_t>(result.second)),
287  cgen_state_->inlineIntNull(ti)});
288  } else {
289  return ts_lv;
290  }
291  }
292  return ti.get_notnull()
293  ? cgen_state_->ir_builder_.CreateSDiv(
294  ts_lv,
295  cgen_state_->llInt(static_cast<int64_t>(
298  "floor_div_nullable_lhs",
299  {ts_lv,
301  cgen_state_->inlineIntNull(ti)});
302 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
const std::pair< SQLOps, int64_t > get_extract_high_precision_adjusted_scale(const ExtractField &field, const int32_t dimen)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:33
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
bool is_high_precision_timestamp() const
Definition: sqltypes.h:1036
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
constexpr bool is_subsecond_extract_field(const ExtractField &field)
Definition: DateTimeUtils.h:95

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegenFixedLengthColVar ( const Analyzer::ColumnVar col_var,
llvm::Value *  col_byte_stream,
llvm::Value *  pos_arg,
const WindowFunctionContext window_function_context = nullptr 
)
private

Definition at line 248 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codgenAdjustFixedEncNull(), CgenState::context_, anonymous_namespace{ColumnIR.cpp}::get_col_bit_width(), anonymous_namespace{ColumnIR.cpp}::get_col_decoder(), get_int_type(), Analyzer::Expr::get_type_info(), WindowFunctionContext::getOrderKeyColumnBufferTypes(), WindowFunctionContext::getWindowFunction(), Analyzer::WindowFunction::hasRangeModeFraming(), CgenState::ir_builder_, kDOUBLE, kENCODING_DICT, kENCODING_FIXED, kENCODING_NONE, kFLOAT, and CgenState::module_.

Referenced by codegenColVar(), and codegenFixedLengthColVarInWindow().

252  {
254  const auto decoder = get_col_decoder(col_var);
255  auto dec_val = decoder->codegenDecode(col_byte_stream, pos_arg, cgen_state_->module_);
256  cgen_state_->ir_builder_.Insert(dec_val);
257  auto dec_type = dec_val->getType();
258  llvm::Value* dec_val_cast{nullptr};
259  const auto& col_ti = col_var->get_type_info();
260  if (dec_type->isIntegerTy()) {
261  auto dec_width = static_cast<llvm::IntegerType*>(dec_type)->getBitWidth();
262  auto col_width = get_col_bit_width(col_var);
263  dec_val_cast = cgen_state_->ir_builder_.CreateCast(
264  static_cast<size_t>(col_width) > dec_width ? llvm::Instruction::CastOps::SExt
265  : llvm::Instruction::CastOps::Trunc,
266  dec_val,
267  get_int_type(col_width, cgen_state_->context_));
268  bool adjust_fixed_enc_null = true;
269  if (window_function_context &&
270  window_function_context->getWindowFunction()->hasRangeModeFraming()) {
271  // we only need to cast it to 8 byte iff it is encoded type
272  // (i.e., the size of non-encoded timestamp type is 8 byte)
273  const auto order_key_ti =
274  window_function_context->getOrderKeyColumnBufferTypes().front();
275  if (order_key_ti.is_timestamp() && order_key_ti.get_size() == 4) {
276  adjust_fixed_enc_null = false;
277  }
278  }
279  if (adjust_fixed_enc_null &&
280  (col_ti.get_compression() == kENCODING_FIXED ||
281  (col_ti.get_compression() == kENCODING_DICT && col_ti.get_size() < 4)) &&
282  !col_ti.get_notnull()) {
283  dec_val_cast = codgenAdjustFixedEncNull(dec_val_cast, col_ti);
284  }
285  } else {
286  CHECK_EQ(kENCODING_NONE, col_ti.get_compression());
287  CHECK(dec_type->isFloatTy() || dec_type->isDoubleTy());
288  if (dec_type->isDoubleTy()) {
289  CHECK(col_ti.get_type() == kDOUBLE);
290  } else if (dec_type->isFloatTy()) {
291  CHECK(col_ti.get_type() == kFLOAT);
292  }
293  dec_val_cast = dec_val;
294  }
295  CHECK(dec_val_cast);
296  return dec_val_cast;
297 }
bool hasRangeModeFraming() const
Definition: Analyzer.h:2959
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
const std::vector< SQLTypeInfo > & getOrderKeyColumnBufferTypes() const
llvm::Value * codgenAdjustFixedEncNull(llvm::Value *, const SQLTypeInfo &)
Definition: ColumnIR.cpp:448
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::shared_ptr< Decoder > get_col_decoder(const Analyzer::ColumnVar *col_var)
Definition: ColumnIR.cpp:29
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
size_t get_col_bit_width(const Analyzer::ColumnVar *col_var)
Definition: ColumnIR.cpp:83
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
#define CHECK(condition)
Definition: Logger.h:291
const Analyzer::WindowFunction * getWindowFunction() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenFixedLengthColVarInWindow ( const Analyzer::ColumnVar col_var,
llvm::Value *  col_byte_stream,
llvm::Value *  pos_arg,
const CompilationOptions co,
const WindowFunctionContext window_function_context = nullptr 
)
private

Definition at line 299 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, CgenState::castToTypeIn(), cgen_state_, CHECK, codegenFixedLengthColVar(), CgenState::context_, WindowFunctionContext::counts(), CodegenUtil::createPtrWithHoistedMemoryAddr(), CgenState::current_func_, executor_, get_int_type(), Analyzer::Expr::get_type_info(), Analyzer::WindowFunction::getArgs(), Analyzer::WindowFunction::getKind(), WindowFunctionContext::getWindowFunction(), CgenState::inlineFpNull(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_fp(), CgenState::llInt(), NTH_VALUE, and WindowFunctionContext::NUM_EXECUTION_DEVICES.

Referenced by codegenColVar().

304  {
306  const auto orig_bb = cgen_state_->ir_builder_.GetInsertBlock();
307  const auto pos_valid_bb = llvm::BasicBlock::Create(
308  cgen_state_->context_, "window.pos_valid", cgen_state_->current_func_);
309  const auto pos_notvalid_bb = llvm::BasicBlock::Create(
310  cgen_state_->context_, "window.pos_notvalid", cgen_state_->current_func_);
311  const auto pos_is_valid =
312  cgen_state_->ir_builder_.CreateICmpSGE(pos_arg, cgen_state_->llInt(int64_t(0)));
313  if (window_function_context->getWindowFunction()->getKind() ==
315  // NTH_VALUE needs to return null if N > partition size
316  // To do this, we store null value to the output buffer of the current row
317  // if following requirements for processing NTH_VALUE are not satisfied
318  // 1. current row is valid
319  // 2. N < partition size that the current row is included
320  const auto window_func_args = window_function_context->getWindowFunction()->getArgs();
321  auto n_value_ptr = dynamic_cast<Analyzer::Constant*>(window_func_args[1].get());
322  auto n_value_lv = cgen_state_->llInt((int64_t)n_value_ptr->get_constval().intval);
323  CHECK(n_value_lv);
324 
325  auto partition_index_lv = executor_->codegenCurrentPartitionIndex(
326  window_function_context, this, co, pos_arg);
327  // # elems per partition
328  const auto pi32_type =
329  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0);
330  const auto partition_count_buf =
331  cgen_state_->llInt(reinterpret_cast<int64_t>(window_function_context->counts()));
332  auto partition_count_buf_ptr_lv = CodegenUtil::createPtrWithHoistedMemoryAddr(
333  cgen_state_,
334  this,
335  co,
336  partition_count_buf,
337  pi32_type,
339  .front();
340 
341  // # elems of the given partition
342  const auto num_elem_current_partition_ptr =
344  partition_count_buf_ptr_lv,
345  partition_index_lv);
346  const auto num_elem_current_partition_lv = cgen_state_->castToTypeIn(
347  cgen_state_->ir_builder_.CreateLoad(
348  num_elem_current_partition_ptr->getType()->getPointerElementType(),
349  num_elem_current_partition_ptr),
350  64);
351  auto is_valid_n_value_lv = cgen_state_->ir_builder_.CreateICmpSLT(
352  n_value_lv, num_elem_current_partition_lv, "is_valid_nth_value");
353  auto cond_lv = cgen_state_->ir_builder_.CreateAnd(
354  is_valid_n_value_lv, pos_is_valid, "is_valid_row_for_nth_value");
355  // return the current row value iff 1) it is a valid row and 2) N < partition_size
356  cgen_state_->ir_builder_.CreateCondBr(cond_lv, pos_valid_bb, pos_notvalid_bb);
357  } else {
358  // return the current row value if it is valid
359  cgen_state_->ir_builder_.CreateCondBr(pos_is_valid, pos_valid_bb, pos_notvalid_bb);
360  }
361  cgen_state_->ir_builder_.SetInsertPoint(pos_valid_bb);
362  const auto fixed_length_column_lv = codegenFixedLengthColVar(
363  col_var, col_byte_stream, pos_arg, window_function_context);
364  cgen_state_->ir_builder_.CreateBr(pos_notvalid_bb);
365  cgen_state_->ir_builder_.SetInsertPoint(pos_notvalid_bb);
366  const auto window_func_call_phi =
367  cgen_state_->ir_builder_.CreatePHI(fixed_length_column_lv->getType(), 2);
368  window_func_call_phi->addIncoming(fixed_length_column_lv, pos_valid_bb);
369  const auto& col_ti = col_var->get_type_info();
370  const auto null_lv =
371  col_ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(col_ti))
372  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(col_ti));
373  window_func_call_phi->addIncoming(null_lv, orig_bb);
374  return window_func_call_phi;
375 }
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
SqlWindowFunctionKind getKind() const
Definition: Analyzer.h:2925
CgenState * cgen_state_
bool is_fp() const
Definition: sqltypes.h:573
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
const int32_t * counts() const
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs() const
Definition: Analyzer.h:2927
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
Executor * executor_
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
static const int NUM_EXECUTION_DEVICES
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
const Analyzer::WindowFunction * getWindowFunction() const
llvm::Value * codegenFixedLengthColVar(const Analyzer::ColumnVar *col_var, llvm::Value *col_byte_stream, llvm::Value *pos_arg, const WindowFunctionContext *window_function_context=nullptr)
Definition: ColumnIR.cpp:248
std::vector< llvm::Value * > createPtrWithHoistedMemoryAddr(CgenState *cgen_state, CodeGenerator *code_generator, CompilationOptions const &co, llvm::ConstantInt *ptr_int_val, llvm::Type *type, size_t num_devices_to_hoist_literal)
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenFpArith ( const Analyzer::BinOper bin_oper,
llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv 
)
private

Definition at line 134 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenDiv(), CgenState::emitCall(), Analyzer::BinOper::get_left_operand(), get_null_check_suffix(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), CgenState::ir_builder_, kDIVIDE, kFLOAT, kMINUS, kMULTIPLY, kPLUS, CgenState::llFp(), NULL_DOUBLE, NULL_FLOAT, and numeric_type_name().

Referenced by codegenArith().

136  {
138  const auto lhs = bin_oper->get_left_operand();
139  const auto rhs = bin_oper->get_right_operand();
140  const auto& lhs_type = lhs->get_type_info();
141  const auto& rhs_type = rhs->get_type_info();
142  const auto fp_typename = numeric_type_name(lhs_type);
143  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
144  llvm::ConstantFP* fp_null{lhs_type.get_type() == kFLOAT
147  switch (bin_oper->get_optype()) {
148  case kMINUS:
149  return null_check_suffix.empty()
150  ? cgen_state_->ir_builder_.CreateFSub(lhs_lv, rhs_lv)
151  : cgen_state_->emitCall("sub_" + fp_typename + null_check_suffix,
152  {lhs_lv, rhs_lv, fp_null});
153  case kPLUS:
154  return null_check_suffix.empty()
155  ? cgen_state_->ir_builder_.CreateFAdd(lhs_lv, rhs_lv)
156  : cgen_state_->emitCall("add_" + fp_typename + null_check_suffix,
157  {lhs_lv, rhs_lv, fp_null});
158  case kMULTIPLY:
159  return null_check_suffix.empty()
160  ? cgen_state_->ir_builder_.CreateFMul(lhs_lv, rhs_lv)
161  : cgen_state_->emitCall("mul_" + fp_typename + null_check_suffix,
162  {lhs_lv, rhs_lv, fp_null});
163  case kDIVIDE:
164  return codegenDiv(lhs_lv,
165  rhs_lv,
166  null_check_suffix.empty() ? "" : fp_typename,
167  null_check_suffix,
168  lhs_type);
169  default:
170  CHECK(false);
171  }
172  CHECK(false);
173  return nullptr;
174 }
#define NULL_DOUBLE
CgenState * cgen_state_
#define NULL_FLOAT
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:43
SQLOps get_optype() const
Definition: Analyzer.h:452
llvm::Value * codegenDiv(llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &, bool upscale=true)
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1661
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
Definition: sqldefs.h:42
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenFunctionOper ( const Analyzer::FunctionOper function_oper,
const CompilationOptions co 
)
private

Definition at line 240 of file ExtensionsIR.cpp.

References run_benchmark_import::args, AUTOMATIC_IR_METADATA, beginArgsNullcheck(), bind_function(), cgen_state_, CHECK, CHECK_EQ, CHECK_GE, codegen(), codegenCast(), codegenFunctionOperCastArgs(), CgenState::context_, gpu_enabled::copy(), CompilationOptions::device_type, CgenState::emitExternalCall(), endArgsNullcheck(), anonymous_namespace{ExtensionsIR.cpp}::ext_arg_type_to_llvm_type(), CgenState::ext_call_cache_, get_arg_by_name(), anonymous_namespace{ExtensionsIR.cpp}::get_buffer_struct_type(), anonymous_namespace{ExtensionsIR.cpp}::get_llvm_type_from_sql_array_type(), Analyzer::UOper::get_operand(), anonymous_namespace{ExtensionsIR.cpp}::get_sql_type_from_llvm_type(), SQLTypeInfo::get_type(), Analyzer::Expr::get_type_info(), Analyzer::FunctionOper::getArg(), Analyzer::FunctionOper::getArity(), ExtensionFunction::getName(), Analyzer::FunctionOper::getName(), ExtensionFunction::getRet(), GPU, CgenState::ir_builder_, Analyzer::ArrayExpr::isLocalAlloc(), kCAST, kPOINT, CgenState::llInt(), LOG, CgenState::row_func_, ExtensionFunction::usesManager(), and logger::WARNING.

Referenced by codegen(), codegenBoundingBoxIntersect(), and codegenFunctionOperWithCustomTypeHandling().

242  {
244  ExtensionFunction ext_func_sig = [=]() {
246  try {
247  return bind_function(function_oper, /* is_gpu= */ true);
248  } catch (ExtensionFunctionBindingError& e) {
249  LOG(WARNING) << "codegenFunctionOper[GPU]: " << e.what() << " Redirecting "
250  << function_oper->getName() << " to run on CPU.";
251  throw QueryMustRunOnCpu();
252  }
253  } else {
254  try {
255  return bind_function(function_oper, /* is_gpu= */ false);
256  } catch (ExtensionFunctionBindingError& e) {
257  LOG(WARNING) << "codegenFunctionOper[CPU]: " << e.what();
258  throw;
259  }
260  }
261  }();
262 
263  const auto& ret_ti = function_oper->get_type_info();
264  CHECK(ret_ti.is_integer() || ret_ti.is_fp() || ret_ti.is_boolean() ||
265  ret_ti.is_buffer() || ret_ti.is_text_encoding_dict());
266  if (ret_ti.is_buffer() && co.device_type == ExecutorDeviceType::GPU) {
267  // TODO: This is not necessary for runtime UDFs because RBC does
268  // not generated GPU LLVM IR when the UDF is using Buffer objects.
269  // However, we cannot remove it until C++ UDFs can be defined for
270  // different devices independently.
271  throw QueryMustRunOnCpu();
272  }
273 
274  auto ret_ty = ext_arg_type_to_llvm_type(ext_func_sig.getRet(), cgen_state_->context_);
275  const auto current_bb = cgen_state_->ir_builder_.GetInsertBlock();
276  for (auto it : cgen_state_->ext_call_cache_) {
277  if (*it.foper == *function_oper) {
278  auto inst = llvm::dyn_cast<llvm::Instruction>(it.lv);
279  if (inst && inst->getParent() == current_bb) {
280  return it.lv;
281  }
282  }
283  }
284  std::vector<llvm::Value*> orig_arg_lvs;
285  std::vector<size_t> orig_arg_lvs_index;
286  std::unordered_map<llvm::Value*, llvm::Value*> const_arr_size;
287 
288  for (size_t i = 0; i < function_oper->getArity(); ++i) {
289  orig_arg_lvs_index.push_back(orig_arg_lvs.size());
290  const auto arg = function_oper->getArg(i);
291  const auto arg_cast = dynamic_cast<const Analyzer::UOper*>(arg);
292  const auto arg0 =
293  (arg_cast && arg_cast->get_optype() == kCAST) ? arg_cast->get_operand() : arg;
294  const auto array_expr_arg = dynamic_cast<const Analyzer::ArrayExpr*>(arg0);
295  auto is_local_alloc = array_expr_arg && array_expr_arg->isLocalAlloc();
296  const auto& arg_ti = arg->get_type_info();
297  const auto arg_lvs = codegen(arg, true, co);
298  auto geo_uoper_arg = dynamic_cast<const Analyzer::GeoUOper*>(arg);
299  auto geo_binoper_arg = dynamic_cast<const Analyzer::GeoBinOper*>(arg);
300  auto geo_expr_arg = dynamic_cast<const Analyzer::GeoExpr*>(arg);
301  // TODO(adb / d): Assuming no const array cols for geo (for now)
302  if ((geo_uoper_arg || geo_binoper_arg) && arg_ti.is_geometry()) {
303  // Extract arr sizes and put them in the map, forward arr pointers
304  CHECK_EQ(2 * static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
305  for (size_t i = 0; i < arg_lvs.size(); i++) {
306  auto arr = arg_lvs[i++];
307  auto size = arg_lvs[i];
308  orig_arg_lvs.push_back(arr);
309  const_arr_size[arr] = size;
310  }
311  } else if (geo_expr_arg && geo_expr_arg->get_type_info().is_geometry()) {
312  CHECK(geo_expr_arg->get_type_info().get_type() == kPOINT);
313  CHECK_EQ(arg_lvs.size(), size_t(2));
314  for (size_t j = 0; j < arg_lvs.size(); j++) {
315  orig_arg_lvs.push_back(arg_lvs[j]);
316  }
317  } else if (arg_ti.is_geometry()) {
318  CHECK_EQ(static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
319  for (size_t j = 0; j < arg_lvs.size(); j++) {
320  orig_arg_lvs.push_back(arg_lvs[j]);
321  }
322  } else if (arg_ti.is_text_encoding_none()) {
323  if (arg_lvs.size() == 3) {
324  // arg_lvs contains:
325  // arg_lvs[0] StringView struct { i8*, i64 }
326  // arg_lvs[1] i8* pointer
327  // arg_lvs[2] i32 string length (truncated from i64)
328  std::copy(
329  std::begin(arg_lvs), std::end(arg_lvs), std::back_inserter(orig_arg_lvs));
330  } else if (arg_lvs.size() == 1) {
331  // TextEncodingNone*
332  // orig_arg_lvs should contain:
333  // orig_arg_lvs[0]: TextEncodingNone struct { i8*, i64, i8* }
334  // orig_arg_lvs[1]: i8*
335  // orig_arg_lvs[1]: i32 string length (truncated from i64)
336  CHECK(arg_lvs[0]->getType()->isPointerTy());
337  auto none_enc_string = cgen_state_->ir_builder_.CreateLoad(
338  arg_lvs[0]->getType()->getPointerElementType(), arg_lvs[0]);
339  orig_arg_lvs.push_back(none_enc_string);
340  orig_arg_lvs.push_back(
341  cgen_state_->ir_builder_.CreateExtractValue(none_enc_string, 0));
342  orig_arg_lvs.push_back(cgen_state_->ir_builder_.CreateTrunc(
343  cgen_state_->ir_builder_.CreateExtractValue(none_enc_string, 1),
344  llvm::Type::getInt32Ty(cgen_state_->context_)));
345  }
346  } else if (arg_ti.is_text_encoding_dict()) {
347  CHECK_EQ(size_t(1), arg_lvs.size());
348  orig_arg_lvs.push_back(arg_lvs[0]);
349  } else {
350  if (arg_lvs.size() > 1) {
351  CHECK(arg_ti.is_array());
352  CHECK_EQ(size_t(2), arg_lvs.size());
353  const_arr_size[arg_lvs.front()] = arg_lvs.back();
354  } else {
355  CHECK_EQ(size_t(1), arg_lvs.size());
356  /* arg_lvs contains:
357  &col_buf1
358  */
359  if (is_local_alloc && arg_ti.get_size() > 0) {
360  const_arr_size[arg_lvs.front()] = cgen_state_->llInt(arg_ti.get_size());
361  }
362  }
363  orig_arg_lvs.push_back(arg_lvs.front());
364  }
365  }
366  // The extension function implementations don't handle NULL, they work under
367  // the assumption that the inputs are validated before calling them. Generate
368  // code to do the check at the call site: if any argument is NULL, return NULL
369  // without calling the function at all.
370  const auto [bbs, null_buffer_ptr] = beginArgsNullcheck(function_oper, orig_arg_lvs);
371  CHECK_GE(orig_arg_lvs.size(), function_oper->getArity());
372  // Arguments must be converted to the types the extension function can handle.
374  function_oper, &ext_func_sig, orig_arg_lvs, orig_arg_lvs_index, const_arr_size, co);
375 
376  if (ext_func_sig.usesManager()) {
378  throw QueryMustRunOnCpu();
379  }
380  llvm::Value* row_func_mgr = get_arg_by_name(cgen_state_->row_func_, "row_func_mgr");
381  args.insert(args.begin(), row_func_mgr);
382  }
383 
384  llvm::Value* buffer_ret{nullptr};
385  if (ret_ti.is_buffer()) {
386  // codegen buffer return as first arg
387  CHECK(ret_ti.is_array() || ret_ti.is_text_encoding_none());
388  ret_ty = llvm::Type::getVoidTy(cgen_state_->context_);
389  const auto struct_ty = get_buffer_struct_type(
390  cgen_state_,
391  function_oper->getName(),
392  0,
394  buffer_ret = cgen_state_->ir_builder_.CreateAlloca(struct_ty);
395  args.insert(args.begin(), buffer_ret);
396  }
397 
398  const auto ext_call = cgen_state_->emitExternalCall(
399  ext_func_sig.getName(), ret_ty, args, {}, ret_ti.is_buffer());
400  auto ext_call_nullcheck = endArgsNullcheck(
401  bbs, ret_ti.is_buffer() ? buffer_ret : ext_call, null_buffer_ptr, function_oper);
402 
403  // Cast the return of the extension function to match the FunctionOper
404  if (!(ret_ti.is_buffer() || ret_ti.is_text_encoding_dict())) {
405  const auto extension_ret_ti = get_sql_type_from_llvm_type(ret_ty);
406  if (bbs.args_null_bb &&
407  extension_ret_ti.get_type() != function_oper->get_type_info().get_type() &&
408  // Skip i1-->i8 casts for ST_ functions.
409  // function_oper ret type is i1, extension ret type is 'upgraded' to i8
410  // during type deserialization to 'handle' NULL returns, hence i1-->i8.
411  // ST_ functions can't return NULLs, we just need to check arg nullness
412  // and if any args are NULL then ST_ function is not called
413  function_oper->getName().substr(0, 3) != std::string("ST_")) {
414  ext_call_nullcheck = codegenCast(ext_call_nullcheck,
415  extension_ret_ti,
416  function_oper->get_type_info(),
417  false,
418  co);
419  }
420  }
421 
422  cgen_state_->ext_call_cache_.push_back({function_oper, ext_call_nullcheck});
423  return ext_call_nullcheck;
424 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
size_t getArity() const
Definition: Analyzer.h:2746
CgenState * cgen_state_
const ExtArgumentType getRet() const
#define LOG(tag)
Definition: Logger.h:285
std::vector< llvm::Value * > codegenFunctionOperCastArgs(const Analyzer::FunctionOper *, const ExtensionFunction *, const std::vector< llvm::Value * > &, const std::vector< size_t > &, const std::unordered_map< llvm::Value *, llvm::Value * > &, const CompilationOptions &)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define CHECK_GE(x, y)
Definition: Logger.h:306
Definition: sqldefs.h:51
const std::string getName(bool keep_suffix=true) const
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
SQLTypeInfo get_sql_type_from_llvm_type(const llvm::Type *ll_type)
llvm::StructType * get_buffer_struct_type(CgenState *cgen_state, const std::string &ext_func_name, size_t param_num, llvm::Type *elem_type)
std::vector< FunctionOperValue > ext_call_cache_
Definition: CgenState.h:390
llvm::Function * row_func_
Definition: CgenState.h:374
llvm::LLVMContext & context_
Definition: CgenState.h:382
std::tuple< ArgNullcheckBBs, llvm::Value * > beginArgsNullcheck(const Analyzer::FunctionOper *function_oper, const std::vector< llvm::Value * > &orig_arg_lvs)
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)
Definition: CgenState.cpp:395
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:168
DEVICE auto copy(ARGS &&...args)
Definition: gpu_enabled.h:51
llvm::Type * get_llvm_type_from_sql_array_type(const SQLTypeInfo ti, llvm::LLVMContext &ctx)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Type * ext_arg_type_to_llvm_type(const ExtArgumentType ext_arg_type, llvm::LLVMContext &ctx)
std::tuple< T, std::vector< SQLTypeInfo > > bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< T > &ext_funcs, const std::string processor)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
bool isLocalAlloc() const
Definition: Analyzer.h:3024
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:2748
const Expr * get_operand() const
Definition: Analyzer.h:384
llvm::Value * endArgsNullcheck(const ArgNullcheckBBs &, llvm::Value *, llvm::Value *, const Analyzer::FunctionOper *)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
std::string getName() const
Definition: Analyzer.h:2744

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenFunctionOperCastArgs ( const Analyzer::FunctionOper function_oper,
const ExtensionFunction ext_func_sig,
const std::vector< llvm::Value * > &  orig_arg_lvs,
const std::vector< size_t > &  orig_arg_lvs_index,
const std::unordered_map< llvm::Value *, llvm::Value * > &  const_arr_size,
const CompilationOptions co 
)
private

Definition at line 1368 of file ExtensionsIR.cpp.

References run_benchmark_import::args, AUTOMATIC_IR_METADATA, castArrayPointer(), cgen_state_, CHECK, CHECK_EQ, CHECK_LE, codegenArrayBuff(), codegenBufferArgs(), codegenCompression(), codegenGeoLineStringArgs(), codegenGeoMultiLineStringArgs(), codegenGeoMultiPointArgs(), codegenGeoMultiPolygonArgs(), codegenGeoPointArgs(), codegenGeoPolygonArgs(), CgenState::context_, CgenState::emitExternalCall(), executor(), GeoMultiLineString, GeoMultiPolygon, GeoPolygon, SQLTypeInfo::get_elem_type(), get_int_type(), Analyzer::Expr::get_type_info(), Analyzer::FunctionOper::getArg(), Analyzer::FunctionOper::getArity(), ExtensionFunction::getInputArgs(), ExtensionFunction::getName(), CgenState::ir_builder_, is_ext_arg_type_array(), is_ext_arg_type_geo(), is_ext_arg_type_pointer(), kARRAY, kENCODING_NONE, kINT, kLINESTRING, kMULTILINESTRING, kMULTIPOINT, kMULTIPOLYGON, kPOINT, kPOLYGON, kTINYINT, ll_bool(), CgenState::llInt(), log2_bytes(), PInt8, posArg(), TextEncodingDict, TextEncodingNone, toString(), and UNREACHABLE.

Referenced by codegenFunctionOper().

1374  {
1376  CHECK(ext_func_sig);
1377  const auto& ext_func_args = ext_func_sig->getInputArgs();
1378  CHECK_LE(function_oper->getArity(), ext_func_args.size());
1379  const auto func_ti = function_oper->get_type_info();
1380  std::vector<llvm::Value*> args;
1381  /*
1382  i: argument in RA for the function operand
1383  j: extra offset in ext_func_args
1384  k: origin_arg_lvs counter, equal to orig_arg_lvs_index[i]
1385  ij: ext_func_args counter, equal to i + j
1386  dj: offset when UDF implementation first argument corresponds to return value
1387  */
1388  for (size_t i = 0, j = 0, dj = (func_ti.is_buffer() ? 1 : 0);
1389  i < function_oper->getArity();
1390  ++i) {
1391  size_t k = orig_arg_lvs_index[i];
1392  size_t ij = i + j;
1393  const auto arg = function_oper->getArg(i);
1394  const auto ext_func_arg = ext_func_args[ij];
1395  const auto& arg_ti = arg->get_type_info();
1396  llvm::Value* arg_lv{nullptr};
1397  if (arg_ti.is_text_encoding_none()) {
1398  CHECK(ext_func_arg == ExtArgumentType::TextEncodingNone)
1399  << ::toString(ext_func_arg);
1400  const auto ptr_lv = orig_arg_lvs[k + 1];
1401  const auto len_lv = orig_arg_lvs[k + 2];
1402  auto& builder = cgen_state_->ir_builder_;
1403  auto string_buf_arg = builder.CreatePointerCast(
1404  ptr_lv, llvm::Type::getInt8PtrTy(cgen_state_->context_));
1405  auto string_size_arg =
1406  builder.CreateZExt(len_lv, get_int_type(64, cgen_state_->context_));
1407  auto padding = ll_int<int8_t>(0, cgen_state_->context_);
1408  codegenBufferArgs(ext_func_sig->getName(),
1409  ij + dj,
1410  string_buf_arg,
1411  string_size_arg,
1412  padding,
1413  args);
1414  } else if (arg_ti.is_text_encoding_dict()) {
1415  CHECK(ext_func_arg == ExtArgumentType::TextEncodingDict)
1416  << ::toString(ext_func_arg);
1417  arg_lv = orig_arg_lvs[k];
1418  args.push_back(arg_lv);
1419  } else if (arg_ti.is_array()) {
1420  bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1421  const auto elem_ti = arg_ti.get_elem_type();
1422  // TODO: switch to fast fixlen variants
1423  const auto ptr_lv = (const_arr)
1424  ? orig_arg_lvs[k]
1426  "array_buff",
1427  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1428  {orig_arg_lvs[k], posArg(arg)});
1429  const auto len_lv =
1430  (const_arr) ? const_arr_size.at(orig_arg_lvs[k])
1432  "array_size",
1434  {orig_arg_lvs[k],
1435  posArg(arg),
1436  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
1437 
1438  if (is_ext_arg_type_pointer(ext_func_arg)) {
1439  args.push_back(castArrayPointer(ptr_lv, elem_ti));
1440  args.push_back(cgen_state_->ir_builder_.CreateZExt(
1441  len_lv, get_int_type(64, cgen_state_->context_)));
1442  j++;
1443  } else if (is_ext_arg_type_array(ext_func_arg)) {
1444  auto array_buf_arg = castArrayPointer(ptr_lv, elem_ti);
1445  auto& builder = cgen_state_->ir_builder_;
1446  auto array_size_arg =
1447  builder.CreateZExt(len_lv, get_int_type(64, cgen_state_->context_));
1448  llvm::Value* array_null_arg = nullptr;
1449  if (auto gep = llvm::dyn_cast<llvm::GetElementPtrInst>(ptr_lv)) {
1450  CHECK(gep->getSourceElementType()->isArrayTy());
1451  // gep has the form
1452  // %17 = getelementptr [9 x i32], [9 x i32]* %7, i32 0
1453  // and was created by passing a const array to the UDF function:
1454  // select array_append({11, 22, 33}, 4);
1455  array_null_arg = ll_bool(false, cgen_state_->context_);
1456  } else {
1457  array_null_arg =
1458  cgen_state_->emitExternalCall("array_is_null",
1460  {orig_arg_lvs[k], posArg(arg)});
1461  }
1462  codegenBufferArgs(ext_func_sig->getName(),
1463  ij + dj,
1464  array_buf_arg,
1465  array_size_arg,
1466  array_null_arg,
1467  args);
1468  } else {
1469  UNREACHABLE();
1470  }
1471 
1472  } else if (arg_ti.is_geometry()) {
1473  auto geo_expr_arg = dynamic_cast<const Analyzer::GeoExpr*>(arg);
1474  if (geo_expr_arg) {
1475  auto ptr_lv = cgen_state_->ir_builder_.CreateBitCast(
1476  orig_arg_lvs[k], llvm::Type::getInt8PtrTy(cgen_state_->context_));
1477  args.push_back(ptr_lv);
1478  // TODO: remove when we normalize extension functions geo sizes to int32
1479  auto size_lv = cgen_state_->ir_builder_.CreateSExt(
1480  orig_arg_lvs[k + 1], llvm::Type::getInt64Ty(cgen_state_->context_));
1481  args.push_back(size_lv);
1482  j++;
1483  continue;
1484  }
1485  // Coords
1486  bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1487  // NOTE(adb): We're generating code to handle the TINYINT array only -- the actual
1488  // geo encoding (or lack thereof) does not matter here
1489  const auto elem_ti = SQLTypeInfo(SQLTypes::kARRAY,
1490  0,
1491  0,
1492  false,
1494  0,
1496  .get_elem_type();
1497  llvm::Value* ptr_lv;
1498  llvm::Value* len_lv;
1499  int32_t fixlen = -1;
1500  if (arg_ti.get_type() == kPOINT) {
1501  const auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(arg);
1502  if (col_var) {
1503  const auto coords_cd = executor()->getPhysicalColumnDescriptor(col_var, 1);
1504  if (coords_cd && coords_cd->columnType.get_type() == kARRAY) {
1505  fixlen = coords_cd->columnType.get_size();
1506  }
1507  }
1508  }
1509  if (fixlen > 0) {
1510  ptr_lv =
1511  cgen_state_->emitExternalCall("fast_fixlen_array_buff",
1512  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1513  {orig_arg_lvs[k], posArg(arg)});
1514  len_lv = cgen_state_->llInt(int32_t(fixlen));
1515  } else {
1516  // TODO: remove const_arr and related code if it's not needed
1517  ptr_lv = (const_arr) ? orig_arg_lvs[k]
1519  "array_buff",
1520  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1521  {orig_arg_lvs[k], posArg(arg)});
1522  len_lv = (const_arr)
1523  ? const_arr_size.at(orig_arg_lvs[k])
1525  "array_size",
1527  {orig_arg_lvs[k],
1528  posArg(arg),
1529  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
1530  }
1531 
1532  if (is_ext_arg_type_geo(ext_func_arg)) {
1533  if (arg_ti.get_type() == kPOINT || arg_ti.get_type() == kLINESTRING ||
1534  arg_ti.get_type() == kMULTIPOINT) {
1535  auto array_buf_arg = castArrayPointer(ptr_lv, elem_ti);
1536  auto compression_val = codegenCompression(arg_ti);
1537  auto input_srid_val = cgen_state_->llInt(arg_ti.get_input_srid());
1538  auto output_srid_val = cgen_state_->llInt(arg_ti.get_output_srid());
1539 
1540  if (arg_ti.get_type() == kPOINT) {
1541  CHECK_EQ(k, ij);
1542  codegenGeoPointArgs(ext_func_sig->getName(),
1543  ij + dj,
1544  array_buf_arg,
1545  len_lv,
1546  compression_val,
1547  input_srid_val,
1548  output_srid_val,
1549  args);
1550  } else if (arg_ti.get_type() == kMULTIPOINT) {
1551  CHECK_EQ(k, ij);
1552  codegenGeoMultiPointArgs(ext_func_sig->getName(),
1553  ij + dj,
1554  array_buf_arg,
1555  len_lv,
1556  compression_val,
1557  input_srid_val,
1558  output_srid_val,
1559  args);
1560  } else {
1561  CHECK_EQ(k, ij);
1562  codegenGeoLineStringArgs(ext_func_sig->getName(),
1563  ij + dj,
1564  array_buf_arg,
1565  len_lv,
1566  compression_val,
1567  input_srid_val,
1568  output_srid_val,
1569  args);
1570  }
1571  }
1572  } else {
1573  CHECK(ext_func_arg == ExtArgumentType::PInt8);
1574  args.push_back(castArrayPointer(ptr_lv, elem_ti));
1575  args.push_back(cgen_state_->ir_builder_.CreateZExt(
1576  len_lv, get_int_type(64, cgen_state_->context_)));
1577  j++;
1578  }
1579 
1580  switch (arg_ti.get_type()) {
1581  case kPOINT:
1582  case kMULTIPOINT:
1583  case kLINESTRING:
1584  break;
1585  case kMULTILINESTRING: {
1586  if (ext_func_arg == ExtArgumentType::GeoMultiLineString) {
1587  auto multi_linestring_coords = castArrayPointer(ptr_lv, elem_ti);
1588  auto compression_val = codegenCompression(arg_ti);
1589  auto input_srid_val = cgen_state_->llInt(arg_ti.get_input_srid());
1590  auto output_srid_val = cgen_state_->llInt(arg_ti.get_output_srid());
1591 
1592  auto [linestring_sizes, linestring_sizes_size] =
1593  codegenArrayBuff(orig_arg_lvs[k + 1],
1594  posArg(arg),
1596  /*cast_and_extend=*/false);
1597  CHECK_EQ(k, ij);
1598  codegenGeoMultiLineStringArgs(ext_func_sig->getName(),
1599  ij + dj,
1600  multi_linestring_coords,
1601  len_lv,
1602  linestring_sizes,
1603  linestring_sizes_size,
1604  compression_val,
1605  input_srid_val,
1606  output_srid_val,
1607  args);
1608  } else {
1609  CHECK(ext_func_arg == ExtArgumentType::PInt8);
1610  // Linestring Sizes
1611  auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1612  auto [linestring_sizes, linestring_sizes_size] =
1613  (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1614  const_arr_size.at(orig_arg_lvs[k + 1]))
1615  : codegenArrayBuff(orig_arg_lvs[k + 1],
1616  posArg(arg),
1618  /*cast_and_extend=*/true);
1619  args.push_back(linestring_sizes);
1620  args.push_back(linestring_sizes_size);
1621  j += 2;
1622  }
1623  break;
1624  }
1625  case kPOLYGON: {
1626  if (ext_func_arg == ExtArgumentType::GeoPolygon) {
1627  auto array_buf_arg = castArrayPointer(ptr_lv, elem_ti);
1628  auto compression_val = codegenCompression(arg_ti);
1629  auto input_srid_val = cgen_state_->llInt(arg_ti.get_input_srid());
1630  auto output_srid_val = cgen_state_->llInt(arg_ti.get_output_srid());
1631 
1632  auto [ring_size_buff, ring_size] =
1633  codegenArrayBuff(orig_arg_lvs[k + 1],
1634  posArg(arg),
1636  /*cast_and_extend=*/false);
1637  CHECK_EQ(k, ij);
1638  codegenGeoPolygonArgs(ext_func_sig->getName(),
1639  ij + dj,
1640  array_buf_arg,
1641  len_lv,
1642  ring_size_buff,
1643  ring_size,
1644  compression_val,
1645  input_srid_val,
1646  output_srid_val,
1647  args);
1648  } else {
1649  CHECK(ext_func_arg == ExtArgumentType::PInt8);
1650  // Ring Sizes
1651  auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1652  auto [ring_size_buff, ring_size] =
1653  (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1654  const_arr_size.at(orig_arg_lvs[k + 1]))
1655  : codegenArrayBuff(orig_arg_lvs[k + 1],
1656  posArg(arg),
1658  /*cast_and_extend=*/true);
1659  args.push_back(ring_size_buff);
1660  args.push_back(ring_size);
1661  j += 2;
1662  }
1663  break;
1664  }
1665  case kMULTIPOLYGON: {
1666  if (ext_func_arg == ExtArgumentType::GeoMultiPolygon) {
1667  auto array_buf_arg = castArrayPointer(ptr_lv, elem_ti);
1668  auto compression_val = codegenCompression(arg_ti);
1669  auto input_srid_val = cgen_state_->llInt(arg_ti.get_input_srid());
1670  auto output_srid_val = cgen_state_->llInt(arg_ti.get_output_srid());
1671 
1672  auto [ring_size_buff, ring_size] =
1673  codegenArrayBuff(orig_arg_lvs[k + 1],
1674  posArg(arg),
1676  /*cast_and_extend=*/false);
1677 
1678  auto [poly_bounds_buff, poly_bounds_size] =
1679  codegenArrayBuff(orig_arg_lvs[k + 2],
1680  posArg(arg),
1682  /*cast_and_extend=*/false);
1683  CHECK_EQ(k, ij);
1684  codegenGeoMultiPolygonArgs(ext_func_sig->getName(),
1685  ij + dj,
1686  array_buf_arg,
1687  len_lv,
1688  ring_size_buff,
1689  ring_size,
1690  poly_bounds_buff,
1691  poly_bounds_size,
1692  compression_val,
1693  input_srid_val,
1694  output_srid_val,
1695  args);
1696  } else {
1697  CHECK(ext_func_arg == ExtArgumentType::PInt8);
1698  // Ring Sizes
1699  {
1700  auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1701  auto [ring_size_buff, ring_size] =
1702  (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1703  const_arr_size.at(orig_arg_lvs[k + 1]))
1704  : codegenArrayBuff(orig_arg_lvs[k + 1],
1705  posArg(arg),
1707  /*cast_and_extend=*/true);
1708 
1709  args.push_back(ring_size_buff);
1710  args.push_back(ring_size);
1711  }
1712  // Poly Rings
1713  {
1714  auto const_arr = const_arr_size.count(orig_arg_lvs[k + 2]) > 0;
1715  auto [poly_bounds_buff, poly_bounds_size] =
1716  (const_arr)
1717  ? std::make_pair(orig_arg_lvs[k + 2],
1718  const_arr_size.at(orig_arg_lvs[k + 2]))
1719  : codegenArrayBuff(
1720  orig_arg_lvs[k + 2], posArg(arg), SQLTypes::kINT, true);
1721 
1722  args.push_back(poly_bounds_buff);
1723  args.push_back(poly_bounds_size);
1724  }
1725  j += 4;
1726  }
1727  break;
1728  }
1729  default:
1730  CHECK(false);
1731  }
1732  } else {
1733  CHECK(is_ext_arg_type_scalar(ext_func_arg));
1734  const auto arg_target_ti = ext_arg_type_to_type_info(ext_func_arg);
1735  if (arg_ti.get_type() != arg_target_ti.get_type()) {
1736  arg_lv = codegenCast(orig_arg_lvs[k], arg_ti, arg_target_ti, false, co);
1737  } else {
1738  arg_lv = orig_arg_lvs[k];
1739  }
1740  CHECK_EQ(arg_lv->getType(),
1742  args.push_back(arg_lv);
1743  }
1744  }
1745  return args;
1746 }
void codegenGeoMultiPolygonArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *polygon_coords, llvm::Value *polygon_coords_size, llvm::Value *ring_sizes_buf, llvm::Value *ring_sizes, llvm::Value *polygon_bounds, llvm::Value *polygon_bounds_sizes, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
bool is_ext_arg_type_scalar(const ExtArgumentType ext_arg_type)
size_t getArity() const
Definition: Analyzer.h:2746
CgenState * cgen_state_
void codegenGeoPolygonArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *polygon_buf, llvm::Value *polygon_size, llvm::Value *ring_sizes_buf, llvm::Value *num_rings, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Value * castArrayPointer(llvm::Value *ptr, const SQLTypeInfo &elem_ti)
#define UNREACHABLE()
Definition: Logger.h:338
const std::string getName(bool keep_suffix=true) const
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
void codegenBufferArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *buffer_buf, llvm::Value *buffer_size, llvm::Value *buffer_is_null, std::vector< llvm::Value * > &output_args)
std::pair< llvm::Value *, llvm::Value * > codegenArrayBuff(llvm::Value *chunk, llvm::Value *row_pos, SQLTypes array_type, bool cast_and_extend)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
bool is_ext_arg_type_geo(const ExtArgumentType ext_arg_type)
void codegenGeoMultiPointArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *multi_point_buf, llvm::Value *multi_point_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
bool is_ext_arg_type_array(const ExtArgumentType ext_arg_type)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Type * ext_arg_type_to_llvm_type(const ExtArgumentType ext_arg_type, llvm::LLVMContext &ctx)
void codegenGeoMultiLineStringArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *multi_linestring_coords, llvm::Value *multi_linestring_size, llvm::Value *linestring_sizes, llvm::Value *linestring_sizes_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
void codegenGeoPointArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *point_buf, llvm::Value *point_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
#define CHECK_LE(x, y)
Definition: Logger.h:304
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:2748
const std::vector< ExtArgumentType > & getInputArgs() const
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
llvm::ConstantInt * ll_bool(const bool v, llvm::LLVMContext &context)
llvm::Value * codegenCompression(const SQLTypeInfo &type_info)
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:198
Definition: sqltypes.h:72
void codegenGeoLineStringArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *line_string_buf, llvm::Value *line_string_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
bool is_ext_arg_type_pointer(const ExtArgumentType ext_arg_type)
SQLTypeInfo get_elem_type() const
Definition: sqltypes.h:977
SQLTypeInfo ext_arg_type_to_type_info(const ExtArgumentType ext_arg_type)
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenFunctionOperNullArg ( const Analyzer::FunctionOper function_oper,
const std::vector< llvm::Value * > &  orig_arg_lvs 
)
private

Definition at line 607 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenIsNullNumber(), CgenState::context_, CgenState::emitExternalCall(), get_int_type(), SQLTypeInfo::get_physical_coord_cols(), Analyzer::Expr::get_type_info(), Analyzer::FunctionOper::getArg(), Analyzer::FunctionOper::getArity(), CgenState::ir_builder_, kENCODING_GEOINT, kPOINT, and posArg().

Referenced by beginArgsNullcheck().

609  {
611  llvm::Value* one_arg_null =
612  llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(cgen_state_->context_), false);
613  size_t physical_coord_cols = 0;
614  for (size_t i = 0, j = 0; i < function_oper->getArity();
615  ++i, j += std::max(size_t(1), physical_coord_cols)) {
616  const auto arg = function_oper->getArg(i);
617  const auto& arg_ti = arg->get_type_info();
618  physical_coord_cols = arg_ti.get_physical_coord_cols();
619  if (arg_ti.get_notnull()) {
620  continue;
621  }
622  auto geo_expr_arg = dynamic_cast<const Analyzer::GeoExpr*>(arg);
623  if (geo_expr_arg && arg_ti.is_geometry()) {
624  CHECK(arg_ti.get_type() == kPOINT);
625  auto is_null_lv = cgen_state_->ir_builder_.CreateICmp(
626  llvm::CmpInst::ICMP_EQ,
627  orig_arg_lvs[j],
628  llvm::ConstantPointerNull::get( // TODO: centralize logic; in geo expr?
629  arg_ti.get_compression() == kENCODING_GEOINT
630  ? llvm::Type::getInt32PtrTy(cgen_state_->context_)
631  : llvm::Type::getDoublePtrTy(cgen_state_->context_)));
632  one_arg_null = cgen_state_->ir_builder_.CreateOr(one_arg_null, is_null_lv);
633  physical_coord_cols = 2; // number of lvs to advance
634  continue;
635  }
636 #ifdef ENABLE_GEOS
637  // If geo arg is coming from geos, skip the null check, assume it's a valid geo
638  if (arg_ti.is_geometry()) {
639  auto* coords_load = llvm::dyn_cast<llvm::LoadInst>(orig_arg_lvs[i]);
640  if (coords_load) {
641  continue;
642  }
643  }
644 #endif
645  if (arg_ti.is_geometry()) {
646  auto* coords_alloca = llvm::dyn_cast<llvm::AllocaInst>(orig_arg_lvs[j]);
647  auto* coords_phi = llvm::dyn_cast<llvm::PHINode>(orig_arg_lvs[j]);
648  if (coords_alloca || coords_phi) {
649  // TODO: null check dynamically generated geometries
650  continue;
651  }
652  }
653  if (arg_ti.is_text_encoding_dict()) {
654  one_arg_null = cgen_state_->ir_builder_.CreateOr(
655  one_arg_null, codegenIsNullNumber(orig_arg_lvs[j], arg_ti));
656  continue;
657  }
658  if (arg_ti.is_buffer() || arg_ti.is_geometry()) {
659  // POINT [un]compressed coord check requires custom checker and chunk iterator
660  // Non-POINT NULL geographies will have a normally encoded null coord array
661  auto fname =
662  (arg_ti.get_type() == kPOINT) ? "point_coord_array_is_null" : "array_is_null";
663  auto is_null_lv = cgen_state_->emitExternalCall(
664  fname, get_int_type(1, cgen_state_->context_), {orig_arg_lvs[j], posArg(arg)});
665  one_arg_null = cgen_state_->ir_builder_.CreateOr(one_arg_null, is_null_lv);
666  continue;
667  }
668  CHECK(arg_ti.is_number() or arg_ti.is_boolean());
669  one_arg_null = cgen_state_->ir_builder_.CreateOr(
670  one_arg_null, codegenIsNullNumber(orig_arg_lvs[j], arg_ti));
671  }
672  return one_arg_null;
673 }
size_t getArity() const
Definition: Analyzer.h:2746
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:2748
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
Definition: LogicalIR.cpp:416
int get_physical_coord_cols() const
Definition: sqltypes.h:451

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenFunctionOperWithCustomTypeHandling ( const Analyzer::FunctionOperWithCustomTypeHandling function_oper,
const CompilationOptions co 
)
private

Definition at line 539 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, beginArgsNullcheck(), anonymous_namespace{ExtensionsIR.cpp}::call_requires_custom_type_handling(), cgen_state_, CHECK, CHECK_EQ, codegen(), codegenCast(), codegenFunctionOper(), CgenState::context_, CgenState::emitCall(), CgenState::emitExternalCall(), endArgsNullcheck(), exp_to_scale(), get_int_type(), Analyzer::Expr::get_type_info(), Analyzer::FunctionOper::getArg(), Analyzer::FunctionOper::getArity(), Analyzer::FunctionOper::getName(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), kINT, and CgenState::llInt().

Referenced by codegen().

541  {
543  if (call_requires_custom_type_handling(function_oper)) {
544  // Some functions need the return type to be the same as the input type.
545  if (function_oper->getName() == "FLOOR" || function_oper->getName() == "CEIL") {
546  CHECK_EQ(size_t(1), function_oper->getArity());
547  const auto arg = function_oper->getArg(0);
548  const auto& arg_ti = arg->get_type_info();
549  CHECK(arg_ti.is_decimal());
550  const auto arg_lvs = codegen(arg, true, co);
551  CHECK_EQ(size_t(1), arg_lvs.size());
552  const auto arg_lv = arg_lvs.front();
553  CHECK(arg_lv->getType()->isIntegerTy(64));
555  std::tie(bbs, std::ignore) = beginArgsNullcheck(function_oper, {arg_lvs});
556  const std::string func_name =
557  (function_oper->getName() == "FLOOR") ? "decimal_floor" : "decimal_ceil";
558  const auto covar_result_lv = cgen_state_->emitCall(
559  func_name, {arg_lv, cgen_state_->llInt(exp_to_scale(arg_ti.get_scale()))});
560  const auto ret_ti = function_oper->get_type_info();
561  CHECK(ret_ti.is_decimal());
562  CHECK_EQ(0, ret_ti.get_scale());
563  const auto result_lv = cgen_state_->ir_builder_.CreateSDiv(
564  covar_result_lv, cgen_state_->llInt(exp_to_scale(arg_ti.get_scale())));
565  return endArgsNullcheck(bbs, result_lv, nullptr, function_oper);
566  } else if (function_oper->getName() == "ROUND" &&
567  function_oper->getArg(0)->get_type_info().is_decimal()) {
568  CHECK_EQ(size_t(2), function_oper->getArity());
569 
570  const auto arg0 = function_oper->getArg(0);
571  const auto& arg0_ti = arg0->get_type_info();
572  const auto arg0_lvs = codegen(arg0, true, co);
573  CHECK_EQ(size_t(1), arg0_lvs.size());
574  const auto arg0_lv = arg0_lvs.front();
575  CHECK(arg0_lv->getType()->isIntegerTy(64));
576 
577  const auto arg1 = function_oper->getArg(1);
578  const auto& arg1_ti = arg1->get_type_info();
579  CHECK(arg1_ti.is_integer());
580  const auto arg1_lvs = codegen(arg1, true, co);
581  auto arg1_lv = arg1_lvs.front();
582  if (arg1_ti.get_type() != kINT) {
583  arg1_lv = codegenCast(arg1_lv, arg1_ti, SQLTypeInfo(kINT, true), false, co);
584  }
585 
587  std::tie(bbs0, std::ignore) =
588  beginArgsNullcheck(function_oper, {arg0_lv, arg1_lvs.front()});
589 
590  const std::string func_name = "Round__4";
591  const auto ret_ti = function_oper->get_type_info();
592  CHECK(ret_ti.is_decimal());
593  const auto result_lv = cgen_state_->emitExternalCall(
594  func_name,
596  {arg0_lv, arg1_lv, cgen_state_->llInt(arg0_ti.get_scale())});
597 
598  return endArgsNullcheck(bbs0, result_lv, nullptr, function_oper);
599  }
600  throw std::runtime_error("Type combination not supported for function " +
601  function_oper->getName());
602  }
603  return codegenFunctionOper(function_oper, co);
604 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
size_t getArity() const
Definition: Analyzer.h:2746
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
bool call_requires_custom_type_handling(const Analyzer::FunctionOper *function_oper)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
std::tuple< ArgNullcheckBBs, llvm::Value * > beginArgsNullcheck(const Analyzer::FunctionOper *function_oper, const std::vector< llvm::Value * > &orig_arg_lvs)
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)
Definition: CgenState.cpp:395
llvm::Value * codegenFunctionOper(const Analyzer::FunctionOper *, const CompilationOptions &)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:2748
llvm::Value * endArgsNullcheck(const ArgNullcheckBBs &, llvm::Value *, llvm::Value *, const Analyzer::FunctionOper *)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
uint64_t exp_to_scale(const unsigned exp)
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
Definition: sqltypes.h:72
std::string getName() const
Definition: Analyzer.h:2744
bool is_decimal() const
Definition: sqltypes.h:570

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoArgs ( const std::vector< std::shared_ptr< Analyzer::Expr >> &  geo_args,
const CompilationOptions co 
)
private

Definition at line 371 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), CgenState::context_, CgenState::emitExternalCall(), get_int_type(), CgenState::ir_builder_, CgenState::llInt(), log2_bytes(), and posArg().

Referenced by codegenGeoBinOper(), and codegenGeoUOper().

373  {
375  std::vector<llvm::Value*> argument_list;
376  bool coord_col = true;
377  for (const auto& geo_arg : geo_args) {
378  const auto arg = geo_arg.get();
379  const auto& arg_ti = arg->get_type_info();
380  const auto elem_ti = arg_ti.get_elem_type();
381  const auto arg_lvs = codegen(arg, true, co);
382  if (arg_ti.is_number()) {
383  argument_list.emplace_back(arg_lvs.front());
384  continue;
385  }
386  if (arg_ti.is_geometry()) {
387  argument_list.insert(argument_list.end(), arg_lvs.begin(), arg_lvs.end());
388  continue;
389  }
390  CHECK(arg_ti.is_array());
391  if (arg_lvs.size() > 1) {
392  CHECK_EQ(size_t(2), arg_lvs.size());
393  auto ptr_lv = arg_lvs.front();
394  if (coord_col) {
395  coord_col = false;
396  } else {
397  ptr_lv = cgen_state_->ir_builder_.CreatePointerCast(
398  ptr_lv, llvm::Type::getInt32PtrTy(cgen_state_->context_));
399  }
400  argument_list.emplace_back(ptr_lv);
401  auto cast_len_lv = cgen_state_->ir_builder_.CreateZExt(
402  arg_lvs.back(), get_int_type(64, cgen_state_->context_));
403  argument_list.emplace_back(cast_len_lv);
404  } else {
405  CHECK_EQ(size_t(1), arg_lvs.size());
406  if (arg_ti.get_size() > 0) {
407  // Set up the pointer lv for a dynamically generated point
408  auto ptr_lv = arg_lvs.front();
409  auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(arg);
410  // Override for point coord column access
411  if (col_var) {
412  ptr_lv = cgen_state_->emitExternalCall(
413  "fast_fixlen_array_buff",
414  llvm::Type::getInt8PtrTy(cgen_state_->context_),
415  {arg_lvs.front(), posArg(arg)});
416  }
417  if (coord_col) {
418  coord_col = false;
419  } else {
420  ptr_lv = cgen_state_->ir_builder_.CreatePointerCast(
421  ptr_lv, llvm::Type::getInt32PtrTy(cgen_state_->context_));
422  }
423  argument_list.emplace_back(ptr_lv);
424  argument_list.emplace_back(cgen_state_->llInt<int64_t>(arg_ti.get_size()));
425  } else {
426  auto ptr_lv =
427  cgen_state_->emitExternalCall("array_buff",
428  llvm::Type::getInt8PtrTy(cgen_state_->context_),
429  {arg_lvs.front(), posArg(arg)});
430  if (coord_col) {
431  coord_col = false;
432  } else {
433  ptr_lv = cgen_state_->ir_builder_.CreatePointerCast(
434  ptr_lv, llvm::Type::getInt32PtrTy(cgen_state_->context_));
435  }
436  argument_list.emplace_back(ptr_lv);
437  const auto len_lv = cgen_state_->emitExternalCall(
438  "array_size",
440  {arg_lvs.front(),
441  posArg(arg),
442  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
443  auto cast_len_lv = cgen_state_->ir_builder_.CreateZExt(
444  len_lv, get_int_type(64, cgen_state_->context_));
445  argument_list.emplace_back(cast_len_lv);
446  }
447  }
448  }
449  return argument_list;
450 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:198

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ArrayLoadCodegen CodeGenerator::codegenGeoArrayLoadAndNullcheck ( llvm::Value *  byte_stream,
llvm::Value *  pos,
const SQLTypeInfo ti,
CgenState cgen_state 
)
static

Definition at line 25 of file GeoIR.cpp.

References CgenState::array_load_cache_, CHECK, CgenState::context_, CgenState::emitExternalCall(), SQLTypeInfo::get_notnull(), SQLTypeInfo::get_type(), and kPOINT.

Referenced by spatial_type::PointAccessors::codegenLoads(), and spatial_type::Transform::codegenLoads().

28  {
29  CHECK(byte_stream);
30 
31  const auto key = std::make_pair(byte_stream, pos);
32  auto cache_itr = cgen_state->array_load_cache_.find(key);
33  if (cache_itr != cgen_state->array_load_cache_.end()) {
34  return cache_itr->second;
35  }
36  const bool is_nullable = !ti.get_notnull();
37  CHECK(ti.get_type() == kPOINT); // TODO: lift this
38 
39  auto pt_arr_buf =
40  cgen_state->emitExternalCall("array_buff",
41  llvm::Type::getInt8PtrTy(cgen_state->context_),
42  {key.first, key.second});
43  llvm::Value* pt_is_null{nullptr};
44  if (is_nullable) {
45  pt_is_null = cgen_state->emitExternalCall("point_coord_array_is_null",
46  llvm::Type::getInt1Ty(cgen_state->context_),
47  {key.first, key.second});
48  }
49  ArrayLoadCodegen arr_load{pt_arr_buf, nullptr, pt_is_null};
50  cgen_state->array_load_cache_.insert(std::make_pair(key, arr_load));
51  return arr_load;
52 }
std::map< std::pair< llvm::Value *, llvm::Value * >, ArrayLoadCodegen > array_load_cache_
Definition: CgenState.h:403
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define CHECK(condition)
Definition: Logger.h:291
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoBinOper ( const Analyzer::GeoBinOper geo_expr,
const CompilationOptions co 
)
private

Definition at line 263 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenGeoArgs(), codegenGeosConstructorCall(), codegenGeosPredicateCall(), CgenState::context_, CompilationOptions::device_type, Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_physical_coord_cols(), SQLTypeInfo::get_type(), Analyzer::Expr::get_type_info(), Analyzer::GeoBinOper::getArgs0(), Analyzer::GeoBinOper::getArgs1(), Analyzer::GeoBinOper::getOp(), Analyzer::GeoBinOper::getTypeInfo0(), Analyzer::GeoBinOper::getTypeInfo1(), GPU, Geospatial::GeoBase::kBUFFER, Geospatial::GeoBase::kCONCAVEHULL, Geospatial::GeoBase::kDIFFERENCE, Geospatial::GeoBase::kEQUALS, Geospatial::GeoBase::kINTERSECTION, Geospatial::GeoBase::kUNION, CgenState::llInt(), and SQLTypeInfo::transforms().

Referenced by codegen().

265  {
268  throw QueryMustRunOnCpu();
269  }
270 #ifndef ENABLE_GEOS
271  throw std::runtime_error("Geo operation requires GEOS support.");
272 #endif
273 
274  auto argument_list = codegenGeoArgs(geo_expr->getArgs0(), co);
275 
276  // Basic set of arguments is currently common to all Geos_* func invocations:
277  // op kind, type of the first geo arg0, geo arg0 components
278  std::string func = "Geos_Wkb"s;
279  if (geo_expr->getTypeInfo0().transforms() || geo_expr->get_type_info().transforms()) {
280  // If there is a transform on the argument and/or on the result of the operation,
281  // verify that the argument's output srid is equal to result's input srid
282  if (geo_expr->getTypeInfo0().get_output_srid() !=
283  geo_expr->get_type_info().get_input_srid()) {
284  throw std::runtime_error("GEOS runtime: input/output srids have to match.");
285  }
286  }
287  // Prepend arg0 geo SQLType
288  argument_list.insert(
289  argument_list.begin(),
290  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_type())));
291  // Prepend geo expr op
292  argument_list.insert(argument_list.begin(),
293  cgen_state_->llInt(static_cast<int>(geo_expr->getOp())));
294  for (auto i = 3; i > geo_expr->getTypeInfo0().get_physical_coord_cols(); i--) {
295  argument_list.insert(argument_list.end(),
296  llvm::ConstantPointerNull::get(
297  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
298  argument_list.insert(argument_list.end(), cgen_state_->llInt(int64_t(0)));
299  }
300  // Append geo expr compression
301  argument_list.insert(
302  argument_list.end(),
303  cgen_state_->llInt(static_cast<int>(
305  // Append geo expr input srid
306  argument_list.insert(
307  argument_list.end(),
308  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_input_srid())));
309  // Append geo expr output srid
310  argument_list.insert(
311  argument_list.end(),
312  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_output_srid())));
313 
314  auto arg1_list = codegenGeoArgs(geo_expr->getArgs1(), co);
315 
316  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kDIFFERENCE ||
318  geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kUNION ||
320  func += "_Wkb"s;
321  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kEQUALS) {
322  func += "_Predicate"s;
323  }
324  // Prepend arg1 geo SQLType
325  arg1_list.insert(
326  arg1_list.begin(),
327  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo1().get_type())));
328  for (auto i = 3; i > geo_expr->getTypeInfo1().get_physical_coord_cols(); i--) {
329  arg1_list.insert(arg1_list.end(),
330  llvm::ConstantPointerNull::get(
331  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
332  arg1_list.insert(arg1_list.end(), cgen_state_->llInt(int64_t(0)));
333  }
334  // Append geo expr compression
335  arg1_list.insert(arg1_list.end(),
336  cgen_state_->llInt(static_cast<int>(
338  // Append geo expr input srid
339  arg1_list.insert(arg1_list.end(),
340  cgen_state_->llInt(geo_expr->getTypeInfo1().get_input_srid()));
341  // Append geo expr output srid
342  arg1_list.insert(arg1_list.end(),
344  } else if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kBUFFER) {
345  // Extra argument in this case is double
346  func += "_double"s;
347  } else if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kCONCAVEHULL) {
348 #if (GEOS_VERSION_MAJOR > 3) || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 11)
349  // Extra argument in this case is double
350  func += "_double"s;
351 #else
352  throw std::runtime_error("ST_ConcaveHull requires GEOS 3.11 or newer");
353 #endif
354  } else {
355  throw std::runtime_error("Unsupported binary geo operation.");
356  }
357 
358  // Append arg1 to the list
359  argument_list.insert(argument_list.end(), arg1_list.begin(), arg1_list.end());
360 
361  // Deal with binary geo predicates
362  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kEQUALS) {
363  return codegenGeosPredicateCall(func, argument_list, co);
364  }
365 
366  auto result_srid = cgen_state_->llInt(geo_expr->get_type_info().get_output_srid());
367 
368  return codegenGeosConstructorCall(func, argument_list, result_srid, co);
369 }
const SQLTypeInfo getTypeInfo0() const
Definition: Analyzer.h:3091
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs0() const
Definition: Analyzer.h:3093
CgenState * cgen_state_
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
const SQLTypeInfo getTypeInfo1() const
Definition: Analyzer.h:3092
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegenGeosConstructorCall(const std::string &, std::vector< llvm::Value * >, llvm::Value *, const CompilationOptions &)
Definition: GeoIR.cpp:485
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegenGeosPredicateCall(const std::string &, std::vector< llvm::Value * >, const CompilationOptions &)
Definition: GeoIR.cpp:452
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:395
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
std::vector< llvm::Value * > codegenGeoArgs(const std::vector< std::shared_ptr< Analyzer::Expr >> &, const CompilationOptions &)
Definition: GeoIR.cpp:371
bool transforms() const
Definition: sqltypes.h:626
int get_physical_coord_cols() const
Definition: sqltypes.h:451
Geospatial::GeoBase::GeoOp getOp() const
Definition: Analyzer.h:3090
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs1() const
Definition: Analyzer.h:3094
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoColumnVar ( const Analyzer::GeoColumnVar geo_col_var,
const bool  fetch_columns,
const CompilationOptions co 
)
private

Definition at line 54 of file GeoIR.cpp.

References CHECK, CHECK_EQ, codegen(), shared::ColumnKey::column_id, get_column_descriptor(), Analyzer::ColumnVar::get_rte_idx(), Analyzer::Expr::get_type_info(), Analyzer::ColumnVar::getColumnKey(), kLINESTRING, kMULTILINESTRING, kMULTIPOLYGON, kPOINT, kPOLYGON, Analyzer::ColumnVar::toString(), and UNREACHABLE.

Referenced by codegen().

57  {
58  auto generate_column_lvs = [this, geo_col_var, &co](const int column_id) {
59  auto column_key = geo_col_var->getColumnKey();
60  column_key.column_id = column_id;
61 
62  auto cd = get_column_descriptor(column_key);
63  CHECK(cd);
64 
65  const auto col_var =
66  Analyzer::ColumnVar(cd->columnType, column_key, geo_col_var->get_rte_idx());
67  const auto lv_vec = codegen(&col_var, /*fetch_columns=*/true, co);
68  CHECK_EQ(lv_vec.size(), size_t(1)); // ptr
69  return lv_vec;
70  };
71 
72  const auto& ti = geo_col_var->get_type_info();
73  switch (ti.get_type()) {
74  case kPOINT:
75  case kLINESTRING:
76  case kMULTILINESTRING:
77  case kPOLYGON:
78  case kMULTIPOLYGON: {
79  std::vector<llvm::Value*> geo_lvs;
80  // iterate over physical columns
81  for (int i = 0; i < ti.get_physical_coord_cols(); i++) {
82  const auto column_id = geo_col_var->getColumnKey().column_id + 1 + i;
83  const auto lvs = generate_column_lvs(column_id);
84  CHECK_EQ(lvs.size(), size_t(1)); // expecting ptr for each column
85  geo_lvs.insert(geo_lvs.end(), lvs.begin(), lvs.end());
86  }
87 
88  return geo_lvs;
89  }
90  default:
91  UNREACHABLE() << geo_col_var->toString();
92  }
93  UNREACHABLE();
94  return {};
95 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define UNREACHABLE()
Definition: Logger.h:338
std::string toString() const override
Definition: Analyzer.cpp:2717
const ColumnDescriptor * get_column_descriptor(const shared::ColumnKey &column_key)
Definition: Execute.h:213
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
#define CHECK(condition)
Definition: Logger.h:291
int32_t get_rte_idx() const
Definition: Analyzer.h:202

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoConstant ( const Analyzer::GeoConstant geo_constant,
const CompilationOptions co 
)
private

Definition at line 111 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, codegen(), CgenState::context_, CgenState::ir_builder_, Analyzer::GeoConstant::makePhysicalConstant(), and Analyzer::GeoConstant::physicalCols().

Referenced by codegen(), and codegenGeoExpr().

113  {
115 
116  std::vector<llvm::Value*> ret;
117  for (size_t i = 0; i < geo_constant->physicalCols(); i++) {
118  auto physical_constant = geo_constant->makePhysicalConstant(i);
119  auto operand_lvs = codegen(physical_constant.get(), /*fetch_columns=*/true, co);
120  CHECK_EQ(operand_lvs.size(), size_t(2));
121  auto array_buff_lv = operand_lvs[0];
122  if (i > 0) {
123  array_buff_lv = cgen_state_->ir_builder_.CreateBitCast(
124  operand_lvs[0], llvm::Type::getInt8PtrTy(cgen_state_->context_));
125  }
126  ret.push_back(array_buff_lv);
127  ret.push_back(operand_lvs[1]);
128  }
129  return ret;
130 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
std::shared_ptr< Analyzer::Constant > makePhysicalConstant(const size_t index) const
Definition: Analyzer.cpp:4087
size_t physicalCols() const
Definition: Analyzer.cpp:4082

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoExpr ( const Analyzer::GeoExpr expr,
const CompilationOptions co 
)
private

Definition at line 97 of file GeoIR.cpp.

References codegenGeoConstant(), codegenGeoOperator(), Analyzer::Expr::toString(), and UNREACHABLE.

Referenced by codegen().

98  {
99  auto geo_constant = dynamic_cast<const Analyzer::GeoConstant*>(expr);
100  if (geo_constant) {
101  return codegenGeoConstant(geo_constant, co);
102  }
103  auto geo_operator = dynamic_cast<const Analyzer::GeoOperator*>(expr);
104  if (geo_operator) {
105  return codegenGeoOperator(geo_operator, co);
106  }
107  UNREACHABLE() << expr->toString();
108  return {};
109 }
#define UNREACHABLE()
Definition: Logger.h:338
std::vector< llvm::Value * > codegenGeoOperator(const Analyzer::GeoOperator *, const CompilationOptions &)
Definition: GeoIR.cpp:149
virtual std::string toString() const =0
std::vector< llvm::Value * > codegenGeoConstant(const Analyzer::GeoConstant *, const CompilationOptions &)
Definition: GeoIR.cpp:111

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenGeoLineStringArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  line_string_buf,
llvm::Value *  line_string_size,
llvm::Value *  compression,
llvm::Value *  input_srid,
llvm::Value *  output_srid,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 972 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, createLineStringStructType(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

979  {
981  CHECK(line_string_buf);
982  CHECK(line_string_size);
983  CHECK(compression);
984  CHECK(input_srid);
985  CHECK(output_srid);
986 
987  auto line_string_abstraction = createLineStringStructType(udf_func_name, param_num);
988  auto alloc_mem =
989  cgen_state_->ir_builder_.CreateAlloca(line_string_abstraction, nullptr);
990 
991  auto line_string_buf_ptr =
992  cgen_state_->ir_builder_.CreateStructGEP(line_string_abstraction, alloc_mem, 0);
993  cgen_state_->ir_builder_.CreateStore(line_string_buf, line_string_buf_ptr);
994 
995  auto line_string_size_ptr =
996  cgen_state_->ir_builder_.CreateStructGEP(line_string_abstraction, alloc_mem, 1);
997  cgen_state_->ir_builder_.CreateStore(line_string_size, line_string_size_ptr);
998 
999  auto line_string_compression_ptr =
1000  cgen_state_->ir_builder_.CreateStructGEP(line_string_abstraction, alloc_mem, 2);
1001  cgen_state_->ir_builder_.CreateStore(compression, line_string_compression_ptr);
1002 
1003  auto input_srid_ptr =
1004  cgen_state_->ir_builder_.CreateStructGEP(line_string_abstraction, alloc_mem, 3);
1005  cgen_state_->ir_builder_.CreateStore(input_srid, input_srid_ptr);
1006 
1007  auto output_srid_ptr =
1008  cgen_state_->ir_builder_.CreateStructGEP(line_string_abstraction, alloc_mem, 4);
1009  cgen_state_->ir_builder_.CreateStore(output_srid, output_srid_ptr);
1010 
1011  output_args.push_back(alloc_mem);
1012 }
llvm::StructType * createLineStringStructType(const std::string &udf_func_name, size_t param_num)
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenGeoMultiLineStringArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  multi_linestring_coords,
llvm::Value *  multi_linestring_size,
llvm::Value *  linestring_sizes,
llvm::Value *  linestring_sizes_size,
llvm::Value *  compression,
llvm::Value *  input_srid,
llvm::Value *  output_srid,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 1066 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, createMultiLineStringStructType(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

1076  {
1078  CHECK(multi_linestring_coords);
1079  CHECK(multi_linestring_coords_size);
1080  CHECK(linestring_sizes);
1081  CHECK(linestring_sizes_size);
1082  CHECK(compression);
1083  CHECK(input_srid);
1084  CHECK(output_srid);
1085 
1086  auto multi_linestring_abstraction =
1087  createMultiLineStringStructType(udf_func_name, param_num);
1088  auto alloc_mem =
1089  cgen_state_->ir_builder_.CreateAlloca(multi_linestring_abstraction, nullptr);
1090 
1091  auto multi_linestring_coords_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1092  multi_linestring_abstraction, alloc_mem, 0);
1093  cgen_state_->ir_builder_.CreateStore(multi_linestring_coords,
1094  multi_linestring_coords_ptr);
1095 
1096  auto multi_linestring_coords_size_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1097  multi_linestring_abstraction, alloc_mem, 1);
1098  cgen_state_->ir_builder_.CreateStore(multi_linestring_coords_size,
1099  multi_linestring_coords_size_ptr);
1100 
1101  auto linestring_sizes_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1102  multi_linestring_abstraction, alloc_mem, 2);
1103  const auto linestring_sizes_ptr_ty =
1104  llvm::dyn_cast<llvm::PointerType>(linestring_sizes_ptr->getType());
1105  CHECK(linestring_sizes_ptr_ty);
1106  cgen_state_->ir_builder_.CreateStore(
1107  cgen_state_->ir_builder_.CreateBitCast(
1108  linestring_sizes, linestring_sizes_ptr_ty->getPointerElementType()),
1109  linestring_sizes_ptr);
1110 
1111  auto linestring_sizes_size_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1112  multi_linestring_abstraction, alloc_mem, 3);
1113  cgen_state_->ir_builder_.CreateStore(linestring_sizes_size, linestring_sizes_size_ptr);
1114 
1115  auto multi_linestring_compression_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1116  multi_linestring_abstraction, alloc_mem, 4);
1117  cgen_state_->ir_builder_.CreateStore(compression, multi_linestring_compression_ptr);
1118 
1119  auto input_srid_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1120  multi_linestring_abstraction, alloc_mem, 5);
1121  cgen_state_->ir_builder_.CreateStore(input_srid, input_srid_ptr);
1122 
1123  auto output_srid_ptr = cgen_state_->ir_builder_.CreateStructGEP(
1124  multi_linestring_abstraction, alloc_mem, 6);
1125  cgen_state_->ir_builder_.CreateStore(output_srid, output_srid_ptr);
1126 
1127  output_args.push_back(alloc_mem);
1128 }
CgenState * cgen_state_
llvm::StructType * createMultiLineStringStructType(const std::string &udf_func_name, size_t param_num)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenGeoMultiPointArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  multi_point_buf,
llvm::Value *  multi_point_size,
llvm::Value *  compression,
llvm::Value *  input_srid,
llvm::Value *  output_srid,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 881 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, createMultiPointStructType(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

888  {
890  CHECK(multi_point_buf);
891  CHECK(multi_point_size);
892  CHECK(compression);
893  CHECK(input_srid);
894  CHECK(output_srid);
895 
896  auto multi_point_abstraction = createMultiPointStructType(udf_func_name, param_num);
897  auto alloc_mem =
898  cgen_state_->ir_builder_.CreateAlloca(multi_point_abstraction, nullptr);
899 
900  auto multi_point_buf_ptr =
901  cgen_state_->ir_builder_.CreateStructGEP(multi_point_abstraction, alloc_mem, 0);
902  cgen_state_->ir_builder_.CreateStore(multi_point_buf, multi_point_buf_ptr);
903 
904  auto multi_point_size_ptr =
905  cgen_state_->ir_builder_.CreateStructGEP(multi_point_abstraction, alloc_mem, 1);
906  cgen_state_->ir_builder_.CreateStore(multi_point_size, multi_point_size_ptr);
907 
908  auto compression_ptr =
909  cgen_state_->ir_builder_.CreateStructGEP(multi_point_abstraction, alloc_mem, 2);
910  cgen_state_->ir_builder_.CreateStore(compression, compression_ptr);
911 
912  auto input_srid_ptr =
913  cgen_state_->ir_builder_.CreateStructGEP(multi_point_abstraction, alloc_mem, 3);
914  cgen_state_->ir_builder_.CreateStore(input_srid, input_srid_ptr);
915 
916  auto output_srid_ptr =
917  cgen_state_->ir_builder_.CreateStructGEP(multi_point_abstraction, alloc_mem, 4);
918  cgen_state_->ir_builder_.CreateStore(output_srid, output_srid_ptr);
919 
920  output_args.push_back(alloc_mem);
921 }
CgenState * cgen_state_
llvm::StructType * createMultiPointStructType(const std::string &udf_func_name, size_t param_num)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenGeoMultiPolygonArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  polygon_coords,
llvm::Value *  polygon_coords_size,
llvm::Value *  ring_sizes_buf,
llvm::Value *  ring_sizes,
llvm::Value *  polygon_bounds,
llvm::Value *  polygon_bounds_sizes,
llvm::Value *  compression,
llvm::Value *  input_srid,
llvm::Value *  output_srid,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 1289 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, createMultiPolygonStructType(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

1300  {
1302  CHECK(polygon_coords);
1303  CHECK(polygon_coords_size);
1304  CHECK(ring_sizes_buf);
1305  CHECK(ring_sizes);
1306  CHECK(polygon_bounds);
1307  CHECK(polygon_bounds_sizes);
1308  CHECK(compression);
1309  CHECK(input_srid);
1310  CHECK(output_srid);
1311 
1312  auto& builder = cgen_state_->ir_builder_;
1313 
1314  auto multi_polygon_abstraction = createMultiPolygonStructType(udf_func_name, param_num);
1315  auto alloc_mem = builder.CreateAlloca(multi_polygon_abstraction, nullptr);
1316 
1317  const auto polygon_coords_ptr =
1318  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 0);
1319  builder.CreateStore(polygon_coords, polygon_coords_ptr);
1320 
1321  const auto polygon_coords_size_ptr =
1322  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 1);
1323  builder.CreateStore(polygon_coords_size, polygon_coords_size_ptr);
1324 
1325  const auto ring_sizes_buf_ptr =
1326  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 2);
1327  const auto ring_sizes_ptr_ty =
1328  llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1329  CHECK(ring_sizes_ptr_ty);
1330  builder.CreateStore(
1331  builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1332  ring_sizes_buf_ptr);
1333 
1334  const auto ring_sizes_ptr =
1335  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 3);
1336  builder.CreateStore(ring_sizes, ring_sizes_ptr);
1337 
1338  const auto polygon_bounds_buf_ptr =
1339  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 4);
1340  const auto bounds_ptr_ty =
1341  llvm::dyn_cast<llvm::PointerType>(polygon_bounds_buf_ptr->getType());
1342  CHECK(bounds_ptr_ty);
1343  builder.CreateStore(
1344  builder.CreateBitCast(polygon_bounds, bounds_ptr_ty->getPointerElementType()),
1345  polygon_bounds_buf_ptr);
1346 
1347  const auto polygon_bounds_sizes_ptr =
1348  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 5);
1349  builder.CreateStore(polygon_bounds_sizes, polygon_bounds_sizes_ptr);
1350 
1351  const auto polygon_compression_ptr =
1352  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 6);
1353  builder.CreateStore(compression, polygon_compression_ptr);
1354 
1355  const auto input_srid_ptr =
1356  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 7);
1357  builder.CreateStore(input_srid, input_srid_ptr);
1358 
1359  const auto output_srid_ptr =
1360  builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 8);
1361  builder.CreateStore(output_srid, output_srid_ptr);
1362 
1363  output_args.push_back(alloc_mem);
1364 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291
llvm::StructType * createMultiPolygonStructType(const std::string &udf_func_name, size_t param_num)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoOperator ( const Analyzer::GeoOperator geo_operator,
const CompilationOptions co 
)
private

Definition at line 149 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegen(), executor(), CgenState::geo_target_cache_, Analyzer::GeoOperator::getName(), spatial_type::Codegen::init(), anonymous_namespace{GeoIR.cpp}::mark_logical_column_to_fetch(), plan_state_, posArg(), and Analyzer::GeoOperator::toString().

Referenced by codegenGeoExpr().

151  {
153 
154  if (geo_operator->getName() == "ST_X" || geo_operator->getName() == "ST_Y") {
155  const auto key = geo_operator->toString();
156  auto geo_target_cache_it = cgen_state_->geo_target_cache_.find(key);
157  if (geo_target_cache_it != cgen_state_->geo_target_cache_.end()) {
158  return {geo_target_cache_it->second};
159  }
160  }
161 
162  auto op_codegen = spatial_type::Codegen::init(geo_operator);
163  CHECK(op_codegen);
164  // we fetch all physical columns, so we sync the logical geo column w/ it
166 
167  std::vector<llvm::Value*> load_lvs;
168  std::vector<llvm::Value*> pos_lvs;
169  for (size_t i = 0; i < op_codegen->size(); i++) {
170  auto intermediate_lvs =
171  codegen(op_codegen->getOperand(i), /*fetch_columns=*/true, co);
172  load_lvs.insert(load_lvs.end(), intermediate_lvs.begin(), intermediate_lvs.end());
173  pos_lvs.push_back(posArg(op_codegen->getOperand(i)));
174  }
175 
176  auto [arg_lvs, null_lv] = op_codegen->codegenLoads(load_lvs, pos_lvs, cgen_state_);
177 
178  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen =
179  op_codegen->getNullCheckCodegen(null_lv, cgen_state_, executor());
180  return op_codegen->codegen(arg_lvs, nullcheck_codegen.get(), cgen_state_, co);
181 }
void mark_logical_column_to_fetch(const Analyzer::GeoOperator *geo_operator, PlanState *plan_state)
Definition: GeoIR.cpp:133
CgenState * cgen_state_
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
std::unordered_map< std::string, llvm::Value * > geo_target_cache_
Definition: CgenState.h:404
const std::string & getName() const
Definition: Analyzer.h:3298
#define AUTOMATIC_IR_METADATA(CGENSTATE)
PlanState * plan_state_
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
#define CHECK(condition)
Definition: Logger.h:291
std::string toString() const override
Definition: Analyzer.cpp:4183
static std::unique_ptr< Codegen > init(const Analyzer::GeoOperator *geo_operator)
Definition: Codegen.cpp:22
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenGeoPointArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  point_buf,
llvm::Value *  point_size,
llvm::Value *  compression,
llvm::Value *  input_srid,
llvm::Value *  output_srid,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 791 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, createPointStructType(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

798  {
800  CHECK(point_buf);
801  CHECK(point_size);
802  CHECK(compression);
803  CHECK(input_srid);
804  CHECK(output_srid);
805 
806  auto point_abstraction = createPointStructType(udf_func_name, param_num);
807  auto alloc_mem = cgen_state_->ir_builder_.CreateAlloca(point_abstraction, nullptr);
808 
809  auto point_buf_ptr =
810  cgen_state_->ir_builder_.CreateStructGEP(point_abstraction, alloc_mem, 0);
811  cgen_state_->ir_builder_.CreateStore(point_buf, point_buf_ptr);
812 
813  auto point_size_ptr =
814  cgen_state_->ir_builder_.CreateStructGEP(point_abstraction, alloc_mem, 1);
815  cgen_state_->ir_builder_.CreateStore(point_size, point_size_ptr);
816 
817  auto point_compression_ptr =
818  cgen_state_->ir_builder_.CreateStructGEP(point_abstraction, alloc_mem, 2);
819  cgen_state_->ir_builder_.CreateStore(compression, point_compression_ptr);
820 
821  auto input_srid_ptr =
822  cgen_state_->ir_builder_.CreateStructGEP(point_abstraction, alloc_mem, 3);
823  cgen_state_->ir_builder_.CreateStore(input_srid, input_srid_ptr);
824 
825  auto output_srid_ptr =
826  cgen_state_->ir_builder_.CreateStructGEP(point_abstraction, alloc_mem, 4);
827  cgen_state_->ir_builder_.CreateStore(output_srid, output_srid_ptr);
828 
829  output_args.push_back(alloc_mem);
830 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::StructType * createPointStructType(const std::string &udf_func_name, size_t param_num)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenGeoPolygonArgs ( const std::string &  udf_func_name,
size_t  param_num,
llvm::Value *  polygon_buf,
llvm::Value *  polygon_size,
llvm::Value *  ring_sizes_buf,
llvm::Value *  num_rings,
llvm::Value *  compression,
llvm::Value *  input_srid,
llvm::Value *  output_srid,
std::vector< llvm::Value * > &  output_args 
)
private

Definition at line 1182 of file ExtensionsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, createPolygonStructType(), and CgenState::ir_builder_.

Referenced by codegenFunctionOperCastArgs().

1191  {
1193  CHECK(polygon_buf);
1194  CHECK(polygon_size);
1195  CHECK(ring_sizes_buf);
1196  CHECK(num_rings);
1197  CHECK(compression);
1198  CHECK(input_srid);
1199  CHECK(output_srid);
1200 
1201  auto& builder = cgen_state_->ir_builder_;
1202 
1203  auto polygon_abstraction = createPolygonStructType(udf_func_name, param_num);
1204  auto alloc_mem = builder.CreateAlloca(polygon_abstraction, nullptr);
1205 
1206  const auto polygon_buf_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 0);
1207  builder.CreateStore(polygon_buf, polygon_buf_ptr);
1208 
1209  const auto polygon_size_ptr =
1210  builder.CreateStructGEP(polygon_abstraction, alloc_mem, 1);
1211  builder.CreateStore(polygon_size, polygon_size_ptr);
1212 
1213  const auto ring_sizes_buf_ptr =
1214  builder.CreateStructGEP(polygon_abstraction, alloc_mem, 2);
1215  const auto ring_sizes_ptr_ty =
1216  llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1217  CHECK(ring_sizes_ptr_ty);
1218  builder.CreateStore(
1219  builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1220  ring_sizes_buf_ptr);
1221 
1222  const auto ring_size_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 3);
1223  builder.CreateStore(num_rings, ring_size_ptr);
1224 
1225  const auto polygon_compression_ptr =
1226  builder.CreateStructGEP(polygon_abstraction, alloc_mem, 4);
1227  builder.CreateStore(compression, polygon_compression_ptr);
1228 
1229  const auto input_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 5);
1230  builder.CreateStore(input_srid, input_srid_ptr);
1231 
1232  const auto output_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 6);
1233  builder.CreateStore(output_srid, output_srid_ptr);
1234 
1235  output_args.push_back(alloc_mem);
1236 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::StructType * createPolygonStructType(const std::string &udf_func_name, size_t param_num)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeosConstructorCall ( const std::string &  func,
std::vector< llvm::Value * >  argument_list,
llvm::Value *  result_srid,
const CompilationOptions co 
)
private

Definition at line 485 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::context_, CgenState::current_func_, CgenState::emitExternalCall(), executor(), get_int_type(), CgenState::ir_builder_, CgenState::llBool(), CgenState::llInt(), CgenState::needs_error_check_, and CgenState::needs_geos_.

Referenced by codegenGeoBinOper(), and codegenGeoUOper().

489  {
491  // Create output buffer pointers, append pointers to output args to
492  auto i8_type = get_int_type(8, cgen_state_->context_);
493  auto i32_type = get_int_type(32, cgen_state_->context_);
494  auto i64_type = get_int_type(64, cgen_state_->context_);
495  auto pi8_type = llvm::PointerType::get(i8_type, 0);
496  auto pi32_type = llvm::PointerType::get(i32_type, 0);
497 
498  auto result_type =
499  cgen_state_->ir_builder_.CreateAlloca(i32_type, nullptr, "result_type");
500  auto result_coords =
501  cgen_state_->ir_builder_.CreateAlloca(pi8_type, nullptr, "result_coords");
502  auto result_coords_size =
503  cgen_state_->ir_builder_.CreateAlloca(i64_type, nullptr, "result_coords_size");
504  auto result_ring_sizes =
505  cgen_state_->ir_builder_.CreateAlloca(pi32_type, nullptr, "result_ring_sizes");
506  auto result_ring_sizes_size =
507  cgen_state_->ir_builder_.CreateAlloca(i64_type, nullptr, "result_ring_sizes_size");
508  auto result_poly_rings =
509  cgen_state_->ir_builder_.CreateAlloca(pi32_type, nullptr, "result_poly_rings");
510  auto result_poly_rings_size =
511  cgen_state_->ir_builder_.CreateAlloca(i64_type, nullptr, "result_poly_rings_size");
512 
513  argument_list.emplace_back(result_type);
514  argument_list.emplace_back(result_coords);
515  argument_list.emplace_back(result_coords_size);
516  argument_list.emplace_back(result_ring_sizes);
517  argument_list.emplace_back(result_ring_sizes_size);
518  argument_list.emplace_back(result_poly_rings);
519  argument_list.emplace_back(result_poly_rings_size);
520  argument_list.emplace_back(result_srid);
521 
522  // Generate call to GEOS wrapper
523  cgen_state_->needs_geos_ = true;
524  auto status_lv = cgen_state_->emitExternalCall(
525  func, llvm::Type::getInt1Ty(cgen_state_->context_), argument_list);
526  // Need to check the status and throw an error if this call has failed.
527  llvm::BasicBlock* geos_ok_bb{nullptr};
528  llvm::BasicBlock* geos_fail_bb{nullptr};
529  geos_ok_bb = llvm::BasicBlock::Create(
530  cgen_state_->context_, "geos_ok_bb", cgen_state_->current_func_);
531  geos_fail_bb = llvm::BasicBlock::Create(
532  cgen_state_->context_, "geos_fail_bb", cgen_state_->current_func_);
533  if (!status_lv) {
534  status_lv = cgen_state_->llBool(false);
535  }
536  cgen_state_->ir_builder_.CreateCondBr(status_lv, geos_ok_bb, geos_fail_bb);
537  cgen_state_->ir_builder_.SetInsertPoint(geos_fail_bb);
538  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt(int32_t(ErrorCode::GEOS)));
540  cgen_state_->ir_builder_.SetInsertPoint(geos_ok_bb);
541 
542  // TODO: Currently forcing the output to MULTIPOLYGON, but need to handle
543  // other possible geometries that geos may return, e.g. a POINT, a LINESTRING
544  // Need to handle empty result, e.g. empty intersection.
545  // The type of result is returned in `result_type`
546 
547  // Load return values
548  auto buf1 = cgen_state_->ir_builder_.CreateLoad(
549  result_coords->getType()->getPointerElementType(), result_coords);
550  auto buf1s = cgen_state_->ir_builder_.CreateLoad(
551  result_coords_size->getType()->getPointerElementType(), result_coords_size);
552  auto buf2 = cgen_state_->ir_builder_.CreateLoad(
553  result_ring_sizes->getType()->getPointerElementType(), result_ring_sizes);
554  auto buf2s = cgen_state_->ir_builder_.CreateLoad(
555  result_ring_sizes_size->getType()->getPointerElementType(), result_ring_sizes_size);
556  auto buf3 = cgen_state_->ir_builder_.CreateLoad(
557  result_poly_rings->getType()->getPointerElementType(), result_poly_rings);
558  auto buf3s = cgen_state_->ir_builder_.CreateLoad(
559  result_poly_rings_size->getType()->getPointerElementType(), result_poly_rings_size);
560 
561  // generate register_buffer_with_executor_rsm() calls to register all output buffers
563  "register_buffer_with_executor_rsm",
564  llvm::Type::getVoidTy(cgen_state_->context_),
565  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
566  cgen_state_->ir_builder_.CreatePointerCast(buf1, pi8_type)});
568  "register_buffer_with_executor_rsm",
569  llvm::Type::getVoidTy(cgen_state_->context_),
570  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
571  cgen_state_->ir_builder_.CreatePointerCast(buf2, pi8_type)});
573  "register_buffer_with_executor_rsm",
574  llvm::Type::getVoidTy(cgen_state_->context_),
575  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
576  cgen_state_->ir_builder_.CreatePointerCast(buf3, pi8_type)});
577 
578  return {cgen_state_->ir_builder_.CreatePointerCast(buf1, pi8_type),
579  buf1s,
580  cgen_state_->ir_builder_.CreatePointerCast(buf2, pi32_type),
581  buf2s,
582  cgen_state_->ir_builder_.CreatePointerCast(buf3, pi32_type),
583  buf3s};
584 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::ConstantInt * llBool(const bool v) const
Definition: CgenState.h:263
bool needs_geos_
Definition: CgenState.h:406
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
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)
Definition: CgenState.cpp:395
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeosPredicateCall ( const std::string &  func,
std::vector< llvm::Value * >  argument_list,
const CompilationOptions co 
)
private

Definition at line 452 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::context_, CgenState::current_func_, CgenState::emitExternalCall(), get_int_type(), CgenState::ir_builder_, CgenState::llBool(), CgenState::llInt(), CgenState::needs_error_check_, CgenState::needs_geos_, run_benchmark_import::res, and run_benchmark_import::result.

Referenced by codegenGeoBinOper(), and codegenGeoUOper().

455  {
457  auto i8_type = get_int_type(8, cgen_state_->context_);
458  auto result = cgen_state_->ir_builder_.CreateAlloca(i8_type, nullptr, "result");
459  argument_list.emplace_back(result);
460 
461  // Generate call to GEOS wrapper
462  cgen_state_->needs_geos_ = true;
463  auto status_lv = cgen_state_->emitExternalCall(
464  func, llvm::Type::getInt1Ty(cgen_state_->context_), argument_list);
465  // Need to check the status and throw an error if this call has failed.
466  llvm::BasicBlock* geos_pred_ok_bb{nullptr};
467  llvm::BasicBlock* geos_pred_fail_bb{nullptr};
468  geos_pred_ok_bb = llvm::BasicBlock::Create(
469  cgen_state_->context_, "geos_pred_ok_bb", cgen_state_->current_func_);
470  geos_pred_fail_bb = llvm::BasicBlock::Create(
471  cgen_state_->context_, "geos_pred_fail_bb", cgen_state_->current_func_);
472  if (!status_lv) {
473  status_lv = cgen_state_->llBool(false);
474  }
475  cgen_state_->ir_builder_.CreateCondBr(status_lv, geos_pred_ok_bb, geos_pred_fail_bb);
476  cgen_state_->ir_builder_.SetInsertPoint(geos_pred_fail_bb);
477  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt(int32_t(ErrorCode::GEOS)));
479  cgen_state_->ir_builder_.SetInsertPoint(geos_pred_ok_bb);
480  auto res = cgen_state_->ir_builder_.CreateLoad(
481  result->getType()->getPointerElementType(), result);
482  return {res};
483 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::ConstantInt * llBool(const bool v) const
Definition: CgenState.h:263
bool needs_geos_
Definition: CgenState.h:406
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
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)
Definition: CgenState.cpp:395
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenGeoUOper ( const Analyzer::GeoUOper geo_expr,
const CompilationOptions co 
)
private

Definition at line 183 of file GeoIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegenGeoArgs(), codegenGeosConstructorCall(), codegenGeosPredicateCall(), CgenState::context_, CompilationOptions::device_type, Geospatial::get_compression_scheme(), SQLTypeInfo::get_input_srid(), SQLTypeInfo::get_output_srid(), SQLTypeInfo::get_physical_coord_cols(), SQLTypeInfo::get_type(), Analyzer::Expr::get_type_info(), Analyzer::GeoUOper::getArgs0(), Analyzer::GeoUOper::getOp(), Analyzer::GeoUOper::getTypeInfo0(), GPU, Geospatial::GeoBase::kCONVEXHULL, Geospatial::GeoBase::kISEMPTY, Geospatial::GeoBase::kISVALID, Geospatial::GeoBase::kPROJECTION, CgenState::llFp(), CgenState::llInt(), and SQLTypeInfo::transforms().

Referenced by codegen().

185  {
188  if (geo_expr->getOp() != Geospatial::GeoBase::GeoOp::kPROJECTION) {
189  throw QueryMustRunOnCpu();
190  }
191  }
192 
193  auto argument_list = codegenGeoArgs(geo_expr->getArgs0(), co);
194 
195  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kPROJECTION) {
196  return argument_list;
197  }
198 
199 #ifndef ENABLE_GEOS
200  throw std::runtime_error("Geo operation requires GEOS support.");
201 #endif
202 
203  // Basic set of arguments is currently common to all Geos_* func invocations:
204  // op kind, type of the first geo arg0, geo arg0 components
205  std::string func = "Geos_Wkb"s;
206 
207  if (geo_expr->getTypeInfo0().transforms() || geo_expr->get_type_info().transforms()) {
208  // If there is a transform on the argument and/or on the result of the operation,
209  // verify that the argument's output srid is equal to result's input srid
210  if (geo_expr->getTypeInfo0().get_output_srid() !=
211  geo_expr->get_type_info().get_input_srid()) {
212  throw std::runtime_error("GEOS runtime: input/output srids have to match.");
213  }
214  }
215  // Prepend arg0 geo SQLType
216  argument_list.insert(
217  argument_list.begin(),
218  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_type())));
219  // Prepend geo expr op
220  argument_list.insert(argument_list.begin(),
221  cgen_state_->llInt(static_cast<int>(geo_expr->getOp())));
222  for (auto i = 3; i > geo_expr->getTypeInfo0().get_physical_coord_cols(); i--) {
223  argument_list.insert(argument_list.end(),
224  llvm::ConstantPointerNull::get(
225  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
226  argument_list.insert(argument_list.end(), cgen_state_->llInt(int64_t(0)));
227  }
228  // Append geo expr compression
229  argument_list.insert(
230  argument_list.end(),
231  cgen_state_->llInt(static_cast<int>(
233  // Append geo expr input srid
234  argument_list.insert(
235  argument_list.end(),
236  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_input_srid())));
237  // Append geo expr output srid
238  argument_list.insert(
239  argument_list.end(),
240  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_output_srid())));
241 
242  // Deal with unary geo predicates
243  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kISEMPTY ||
245  return codegenGeosPredicateCall(func, argument_list, co);
246  }
247 
248  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kCONVEXHULL) {
249  func += "_double"s; // Use same interface as ST_ConcaveHull, with a dummy double
250 
251  // Insert that dummy double arg
252  argument_list.insert(argument_list.end(), cgen_state_->llFp(double(0)));
253 
254  auto result_srid = cgen_state_->llInt(geo_expr->get_type_info().get_output_srid());
255 
256  return codegenGeosConstructorCall(func, argument_list, result_srid, co);
257  }
258 
259  throw std::runtime_error("Unsupported unary geo operation.");
260  return {};
261 }
const SQLTypeInfo getTypeInfo0() const
Definition: Analyzer.h:3062
CgenState * cgen_state_
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::LLVMContext & context_
Definition: CgenState.h:382
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs0() const
Definition: Analyzer.h:3063
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegenGeosConstructorCall(const std::string &, std::vector< llvm::Value * >, llvm::Value *, const CompilationOptions &)
Definition: GeoIR.cpp:485
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegenGeosPredicateCall(const std::string &, std::vector< llvm::Value * >, const CompilationOptions &)
Definition: GeoIR.cpp:452
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:395
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
std::vector< llvm::Value * > codegenGeoArgs(const std::vector< std::shared_ptr< Analyzer::Expr >> &, const CompilationOptions &)
Definition: GeoIR.cpp:371
Geospatial::GeoBase::GeoOp getOp() const
Definition: Analyzer.h:3061
bool transforms() const
Definition: sqltypes.h:626
int get_physical_coord_cols() const
Definition: sqltypes.h:451
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenHoistedConstants ( const std::vector< const Analyzer::Constant * > &  constants,
const EncodingType  enc_type,
const shared::StringDictKey dict_id 
)

Definition at line 373 of file ConstantIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, CHECK_GE, codegenHoistedConstantsLoads(), codegenHoistedConstantsPlaceholders(), Analyzer::Expr::get_type_info(), CgenState::getOrAddLiteral(), and CgenState::query_func_literal_loads_.

Referenced by TreeModelPredictionMgr::codegen(), codegen(), CodegenUtil::createPtrWithHoistedMemoryAddr(), CodegenUtil::hoistLiteral(), and InValuesBitmap::prepareBitIsSetParams().

376  {
378  CHECK(!constants.empty());
379  const auto& type_info = constants.front()->get_type_info();
380  checked_int16_t checked_lit_off{0};
381  size_t next_lit_bytes{0};
382  int16_t lit_off{-1};
383  size_t lit_bytes;
384  try {
385  // currently, we assume that `constants.size()` indicates the number of devices
386  // which is equivalent to the total number of devices that a system has
387  // so we need to revisit this to support the selection of devices to execute
388  // the query (i.e., use GPU 1 and 4 to execute the query among eight GPUs)
389  // todo (yoonmin) : indicate a set of devices to hoist a literal
390  for (size_t device_id = 0; device_id < constants.size(); ++device_id) {
391  const auto constant = constants[device_id];
392  const auto& crt_type_info = constant->get_type_info();
393  CHECK(type_info == crt_type_info);
394  std::tie(checked_lit_off, next_lit_bytes) =
395  cgen_state_->getOrAddLiteral(constant, enc_type, dict_id, device_id);
396  if (device_id) {
397  CHECK_EQ(lit_off, checked_lit_off);
398  CHECK_EQ(lit_bytes, next_lit_bytes);
399  } else {
400  lit_off = static_cast<int16_t>(checked_lit_off);
401  lit_bytes = next_lit_bytes;
402  }
403  }
404  } catch (const std::range_error& e) {
405  // detect literal buffer overflow when trying to
406  // assign literal buf offset which is not in a valid range
407  // to checked_type variable
408  throw TooManyLiterals();
409  }
410  CHECK_GE(lit_off, 0);
411  std::vector<llvm::Value*> hoisted_literal_loads;
412  auto entry = cgen_state_->query_func_literal_loads_.find(lit_off);
413 
414  if (entry == cgen_state_->query_func_literal_loads_.end()) {
415  hoisted_literal_loads =
416  codegenHoistedConstantsLoads(type_info, enc_type, dict_id, lit_off, lit_bytes);
417  cgen_state_->query_func_literal_loads_[lit_off] = hoisted_literal_loads;
418  } else {
419  hoisted_literal_loads = entry->second;
420  }
421 
422  std::vector<llvm::Value*> literal_placeholders = codegenHoistedConstantsPlaceholders(
423  type_info, enc_type, lit_off, hoisted_literal_loads);
424  return literal_placeholders;
425 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 15, 15, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void >> checked_int16_t
#define CHECK_GE(x, y)
Definition: Logger.h:306
std::unordered_map< int, std::vector< llvm::Value * > > query_func_literal_loads_
Definition: CgenState.h:410
std::vector< llvm::Value * > codegenHoistedConstantsLoads(const SQLTypeInfo &type_info, const EncodingType enc_type, const shared::StringDictKey &dict_id, const int16_t lit_off, const size_t lit_bytes)
Definition: ConstantIR.cpp:142
std::vector< llvm::Value * > codegenHoistedConstantsPlaceholders(const SQLTypeInfo &type_info, const EncodingType enc_type, const int16_t lit_off, const std::vector< llvm::Value * > &literal_loads)
Definition: ConstantIR.cpp:280
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291
std::tuple< size_t, size_t > getOrAddLiteral(const Analyzer::Constant *constant, const EncodingType enc_type, const shared::StringDictKey &dict_id, const int device_id)
Definition: CgenState.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenHoistedConstantsLoads ( const SQLTypeInfo type_info,
const EncodingType  enc_type,
const shared::StringDictKey dict_id,
const int16_t  lit_off,
const size_t  lit_bytes 
)
private

Definition at line 142 of file ConstantIR.cpp.

References AUTOMATIC_IR_METADATA, shared::bit_cast(), cgen_state_, CHECK, CHECK_EQ, CgenState::context_, CgenState::emitEntryCall(), logger::ERROR, g_allow_invalid_literal_buffer_reads, get_arg_by_name(), get_bit_width(), SQLTypeInfo::get_compression(), SQLTypeInfo::get_dimension(), get_int_type(), anonymous_namespace{ColumnIR.cpp}::get_phys_int_type(), SQLTypeInfo::get_scale(), SQLTypeInfo::get_subtype(), SQLTypeInfo::get_type(), CgenState::inlineIntNull(), SQLTypeInfo::is_array(), SQLTypeInfo::is_boolean(), SQLTypeInfo::is_decimal(), SQLTypeInfo::is_geometry(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_string(), SQLTypeInfo::is_time(), SQLTypeInfo::is_timeinterval(), kDOUBLE, kENCODING_DICT, kENCODING_GEOINT, kENCODING_NONE, kFLOAT, kTINYINT, CgenState::literalBytes(), CgenState::llInt(), LOG, CgenState::query_func_, CgenState::query_func_entry_ir_builder_, to_string(), SQLTypeInfo::to_string(), and toString().

Referenced by codegenHoistedConstants().

147  {
149  std::string literal_name = "literal_" + std::to_string(lit_off);
150  auto lit_buff_query_func_lv = get_arg_by_name(cgen_state_->query_func_, "literals");
151  const auto lit_buf_start = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
152  lit_buff_query_func_lv->getType()->getScalarType()->getPointerElementType(),
153  lit_buff_query_func_lv,
154  cgen_state_->llInt(lit_off));
155  CHECK(!type_info.is_geometry());
156  if (type_info.is_string() && enc_type != kENCODING_DICT) {
158  CHECK_EQ(size_t(4),
160  auto off_and_len_ptr = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(
161  lit_buf_start,
162  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0));
163  // packed offset + length, 16 bits each
164  auto off_and_len = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
165  off_and_len_ptr->getType()->getPointerElementType(), off_and_len_ptr);
166  auto off_lv = cgen_state_->query_func_entry_ir_builder_.CreateLShr(
168  off_and_len, cgen_state_->llInt(int32_t(0xffff0000))),
169  cgen_state_->llInt(int32_t(16)));
170  auto len_lv = cgen_state_->query_func_entry_ir_builder_.CreateAnd(
171  off_and_len, cgen_state_->llInt(int32_t(0x0000ffff)));
172 
173  auto var_start = cgen_state_->llInt(int64_t(0));
174  auto var_start_address = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
175  lit_buff_query_func_lv->getType()->getScalarType()->getPointerElementType(),
176  lit_buff_query_func_lv,
177  off_lv);
178  auto var_length = len_lv;
179 
180  var_start->setName(literal_name + "_start");
181  var_start_address->setName(literal_name + "_start_address");
182  var_length->setName(literal_name + "_length");
183 
184  return {var_start, var_start_address, var_length};
185  } else if (type_info.is_array() &&
186  (enc_type == kENCODING_NONE || enc_type == kENCODING_GEOINT)) {
187  if (enc_type == kENCODING_NONE) {
189  } else if (enc_type == kENCODING_GEOINT) {
191  CHECK_EQ(kTINYINT, type_info.get_subtype());
192  }
193 
194  auto off_and_len_ptr = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(
195  lit_buf_start,
196  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0));
197  // packed offset + length, 16 bits each
198  auto off_and_len = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
199  off_and_len_ptr->getType()->getPointerElementType(), off_and_len_ptr);
200  auto off_lv = cgen_state_->query_func_entry_ir_builder_.CreateLShr(
202  off_and_len, cgen_state_->llInt(int32_t(0xffff0000))),
203  cgen_state_->llInt(int32_t(16)));
204  auto len_lv = cgen_state_->query_func_entry_ir_builder_.CreateAnd(
205  off_and_len, cgen_state_->llInt(int32_t(0x0000ffff)));
206 
207  auto var_start_address = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
208  lit_buff_query_func_lv->getType()->getScalarType()->getPointerElementType(),
209  lit_buff_query_func_lv,
210  off_lv);
211  auto var_length = len_lv;
212 
213  var_start_address->setName(literal_name + "_start_address");
214  var_length->setName(literal_name + "_length");
215 
216  return {var_start_address, var_length};
217  }
218 
219  // Load a literal from the literal buffer. See also getOrAddLiteral().
220  llvm::Type* val_ptr_type{nullptr};
221  // NOTE(sy): If val_bits_in is ever different from val_bits_out, that means we need to
222  // generate casting below for the type that has this happen. Currently only the decimal
223  // type is known to ever have this happen.
224  const size_t lit_bits = lit_bytes * 8;
225  const size_t val_bits_out = get_bit_width(type_info);
226  const size_t val_bits_in = type_info.is_decimal() ? lit_bits : val_bits_out;
227  if (val_bits_in != lit_bits && !g_allow_invalid_literal_buffer_reads) {
228  // Refuse to read the wrong number of bytes from the literal buffer.
229  std::stringstream ss;
230  ss << "Invalid literal buffer read size " << val_bits_in << " (expected " << lit_bits
231  << ") for type " << toString(type_info.get_type())
232  << ". See also: --allow-invalid-literal-buffer-reads";
233  LOG(ERROR) << "ERROR: " << ss.str();
234  LOG(ERROR) << type_info.to_string();
235  throw std::runtime_error(ss.str());
236  }
237  CHECK_EQ(size_t(0), val_bits_in % 8);
238  CHECK_EQ(size_t(0), val_bits_out % 8);
239  if (type_info.is_integer() || type_info.is_decimal() || type_info.is_time() ||
240  type_info.is_timeinterval() || type_info.is_string() || type_info.is_boolean()) {
241  val_ptr_type = llvm::PointerType::get(
242  llvm::IntegerType::get(cgen_state_->context_, val_bits_in), 0);
243  } else {
244  CHECK(type_info.get_type() == kFLOAT || type_info.get_type() == kDOUBLE);
245  val_ptr_type = (type_info.get_type() == kFLOAT)
246  ? llvm::Type::getFloatPtrTy(cgen_state_->context_)
247  : llvm::Type::getDoublePtrTy(cgen_state_->context_);
248  }
249  auto* bit_cast = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(lit_buf_start,
250  val_ptr_type);
251  llvm::Value* lit_lv = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
252  bit_cast->getType()->getPointerElementType(), bit_cast);
253  if (type_info.is_decimal() && val_bits_in != val_bits_out) {
254  // Generate casting.
255  SQLTypeInfo type_info_in(get_phys_int_type(val_bits_in / 8),
256  type_info.get_dimension(),
257  type_info.get_scale(),
258  false,
260  0,
261  type_info.get_subtype());
262  SQLTypeInfo type_info_out(get_phys_int_type(val_bits_out / 8),
263  type_info.get_dimension(),
264  type_info.get_scale(),
265  false,
267  0,
268  type_info.get_subtype());
269  lit_lv = cgen_state_->emitEntryCall("cast_int" + std::to_string(val_bits_in) +
270  "_t_to_int" + std::to_string(val_bits_out) +
271  "_t_nullable",
272  {lit_lv,
273  cgen_state_->inlineIntNull(type_info_in),
274  cgen_state_->inlineIntNull(type_info_out)});
275  }
276  lit_lv->setName(literal_name);
277  return {lit_lv};
278 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
#define CHECK_EQ(x, y)
Definition: Logger.h:301
llvm::Value * emitEntryCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:229
CgenState * cgen_state_
#define LOG(tag)
Definition: Logger.h:285
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
llvm::Function * query_func_
Definition: CgenState.h:408
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool is_time() const
Definition: sqltypes.h:579
std::string to_string(char const *&&v)
static size_t literalBytes(const CgenState::LiteralValue &lit)
Definition: CgenState.h:418
boost::variant< int8_t, int16_t, int32_t, int64_t, float, double, std::pair< std::string, shared::StringDictKey >, std::string, std::vector< double >, std::vector< int32_t >, std::vector< int8_t >, std::pair< std::vector< int8_t >, int >> LiteralValue
Definition: CgenState.h:185
std::string to_string() const
Definition: sqltypes.h:528
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:168
bool is_integer() const
Definition: sqltypes.h:567
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool is_timeinterval() const
Definition: sqltypes.h:594
bool is_boolean() const
Definition: sqltypes.h:582
llvm::IRBuilder query_func_entry_ir_builder_
Definition: CgenState.h:409
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
TO bit_cast(FROM &&from)
Definition: misc.h:307
bool g_allow_invalid_literal_buffer_reads
Definition: ConstantIR.cpp:140
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool is_geometry() const
Definition: sqltypes.h:597
bool is_string() const
Definition: sqltypes.h:561
bool is_decimal() const
Definition: sqltypes.h:570
SQLTypes get_phys_int_type(const size_t byte_sz)
Definition: ColumnIR.cpp:429
bool is_array() const
Definition: sqltypes.h:585

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenHoistedConstantsPlaceholders ( const SQLTypeInfo type_info,
const EncodingType  enc_type,
const int16_t  lit_off,
const std::vector< llvm::Value * > &  literal_loads 
)
private

Definition at line 280 of file ConstantIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, CgenState::ir_builder_, SQLTypeInfo::is_array(), SQLTypeInfo::is_geometry(), SQLTypeInfo::is_string(), kENCODING_DICT, kENCODING_GEOINT, kENCODING_NONE, CgenState::llInt(), CgenState::row_func_hoisted_literals_, and to_string().

Referenced by codegenHoistedConstants().

284  {
286  std::string literal_name = "literal_" + std::to_string(lit_off);
287  CHECK(!type_info.is_geometry());
288 
289  if (type_info.is_string() && enc_type != kENCODING_DICT) {
290  CHECK_EQ(literal_loads.size(), 3u);
291 
292  llvm::Value* var_start = literal_loads[0];
293  llvm::Value* var_start_address = literal_loads[1];
294  llvm::Value* var_length = literal_loads[2];
295 
296  llvm::PointerType* placeholder0_type =
297  llvm::PointerType::get(var_start->getType(), 0);
298  auto* int_to_ptr0 =
299  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder0_type);
300  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
301  int_to_ptr0->getType()->getPointerElementType(),
302  int_to_ptr0,
303  "__placeholder__" + literal_name + "_start");
304  llvm::PointerType* placeholder1_type =
305  llvm::PointerType::get(var_start_address->getType(), 0);
306  auto* int_to_ptr1 =
307  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder1_type);
308  auto placeholder1 = cgen_state_->ir_builder_.CreateLoad(
309  int_to_ptr1->getType()->getPointerElementType(),
310  int_to_ptr1,
311  "__placeholder__" + literal_name + "_start_address");
312  llvm::PointerType* placeholder2_type =
313  llvm::PointerType::get(var_length->getType(), 0);
314  auto* int_to_ptr2 =
315  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder2_type);
316  auto placeholder2 = cgen_state_->ir_builder_.CreateLoad(
317  int_to_ptr2->getType()->getPointerElementType(),
318  int_to_ptr2,
319  "__placeholder__" + literal_name + "_length");
320 
321  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
322  cgen_state_->row_func_hoisted_literals_[placeholder1] = {lit_off, 1};
323  cgen_state_->row_func_hoisted_literals_[placeholder2] = {lit_off, 2};
324 
325  return {placeholder0, placeholder1, placeholder2};
326  }
327 
328  if (type_info.is_array() &&
329  (enc_type == kENCODING_NONE || enc_type == kENCODING_GEOINT)) {
330  CHECK_EQ(literal_loads.size(), 2u);
331 
332  llvm::Value* var_start_address = literal_loads[0];
333  llvm::Value* var_length = literal_loads[1];
334 
335  llvm::PointerType* placeholder0_type =
336  llvm::PointerType::get(var_start_address->getType(), 0);
337  auto* int_to_ptr0 =
338  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder0_type);
339  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
340  int_to_ptr0->getType()->getPointerElementType(),
341  int_to_ptr0,
342  "__placeholder__" + literal_name + "_start_address");
343  llvm::PointerType* placeholder1_type =
344  llvm::PointerType::get(var_length->getType(), 0);
345  auto* int_to_ptr1 =
346  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder1_type);
347  auto placeholder1 = cgen_state_->ir_builder_.CreateLoad(
348  int_to_ptr1->getType()->getPointerElementType(),
349  int_to_ptr1,
350  "__placeholder__" + literal_name + "_length");
351 
352  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
353  cgen_state_->row_func_hoisted_literals_[placeholder1] = {lit_off, 1};
354 
355  return {placeholder0, placeholder1};
356  }
357 
358  CHECK_EQ(literal_loads.size(), 1u);
359  llvm::Value* to_return_lv = literal_loads[0];
360 
361  auto* int_to_ptr = cgen_state_->ir_builder_.CreateIntToPtr(
362  cgen_state_->llInt(0), llvm::PointerType::get(to_return_lv->getType(), 0));
363  auto placeholder0 =
364  cgen_state_->ir_builder_.CreateLoad(int_to_ptr->getType()->getPointerElementType(),
365  int_to_ptr,
366  "__placeholder__" + literal_name);
367 
368  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
369 
370  return {placeholder0};
371 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
std::unordered_map< llvm::Value *, HoistedLiteralLoadLocator > row_func_hoisted_literals_
Definition: CgenState.h:416
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
std::string to_string(char const *&&v)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool is_geometry() const
Definition: sqltypes.h:597
bool is_string() const
Definition: sqltypes.h:561
bool is_array() const
Definition: sqltypes.h:585

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenIntArith ( const Analyzer::BinOper bin_oper,
llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const CompilationOptions co 
)
private

Definition at line 77 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenAdd(), codegenDiv(), codegenMod(), codegenMul(), codegenSub(), Analyzer::BinOper::get_left_operand(), get_null_check_suffix(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), kDIVIDE, kMINUS, kMODULO, kMULTIPLY, kPLUS, and anonymous_namespace{ArithmeticIR.cpp}::numeric_or_time_interval_type_name().

Referenced by codegenArith().

80  {
82  const auto lhs = bin_oper->get_left_operand();
83  const auto rhs = bin_oper->get_right_operand();
84  const auto& lhs_type = lhs->get_type_info();
85  const auto& rhs_type = rhs->get_type_info();
86  const auto int_typename = numeric_or_time_interval_type_name(lhs_type, rhs_type);
87  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
88  const auto& oper_type = rhs_type.is_timeinterval() ? rhs_type : lhs_type;
89  switch (bin_oper->get_optype()) {
90  case kMINUS:
91  return codegenSub(bin_oper,
92  lhs_lv,
93  rhs_lv,
94  null_check_suffix.empty() ? "" : int_typename,
95  null_check_suffix,
96  oper_type,
97  co);
98  case kPLUS:
99  return codegenAdd(bin_oper,
100  lhs_lv,
101  rhs_lv,
102  null_check_suffix.empty() ? "" : int_typename,
103  null_check_suffix,
104  oper_type,
105  co);
106  case kMULTIPLY:
107  return codegenMul(bin_oper,
108  lhs_lv,
109  rhs_lv,
110  null_check_suffix.empty() ? "" : int_typename,
111  null_check_suffix,
112  oper_type,
113  co);
114  case kDIVIDE:
115  return codegenDiv(lhs_lv,
116  rhs_lv,
117  null_check_suffix.empty() ? "" : int_typename,
118  null_check_suffix,
119  oper_type);
120  case kMODULO:
121  return codegenMod(lhs_lv,
122  rhs_lv,
123  null_check_suffix.empty() ? "" : int_typename,
124  null_check_suffix,
125  oper_type);
126  default:
127  CHECK(false);
128  }
129  CHECK(false);
130  return nullptr;
131 }
CgenState * cgen_state_
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::Value * codegenMod(llvm::Value *, llvm::Value *, const std::string &null_typename, const std::string &null_check_suffix, const SQLTypeInfo &)
Definition: sqldefs.h:43
SQLOps get_optype() const
Definition: Analyzer.h:452
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)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1661
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
Definition: sqldefs.h:42
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 &)
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455
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)
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 &)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::ConstantInt * CodeGenerator::codegenIntConst ( const Analyzer::Constant constant,
CgenState cgen_state 
)
static

Definition at line 89 of file ConstantIR.cpp.

References Datum::bigintval, decimal_to_int_type(), Analyzer::Constant::get_constval(), Analyzer::Constant::get_is_null(), Analyzer::Expr::get_type_info(), CgenState::inlineIntNull(), Datum::intval, kBIGINT, kDATE, kINT, kINTERVAL_DAY_TIME, kINTERVAL_YEAR_MONTH, kSMALLINT, kTIME, kTIMESTAMP, kTINYINT, CgenState::llInt(), Datum::smallintval, Datum::tinyintval, run_benchmark_import::type, and UNREACHABLE.

Referenced by codegen(), codegenDeciDiv(), createInValuesBitmap(), and Executor::skipFragment().

90  {
91  const auto& type_info = constant->get_type_info();
92  if (constant->get_is_null()) {
93  return cgen_state->inlineIntNull(type_info);
94  }
95  const auto type =
96  type_info.is_decimal() ? decimal_to_int_type(type_info) : type_info.get_type();
97  switch (type) {
98  case kTINYINT:
99  return cgen_state->llInt(constant->get_constval().tinyintval);
100  case kSMALLINT:
101  return cgen_state->llInt(constant->get_constval().smallintval);
102  case kINT:
103  return cgen_state->llInt(constant->get_constval().intval);
104  case kBIGINT:
105  return cgen_state->llInt(constant->get_constval().bigintval);
106  case kTIME:
107  case kTIMESTAMP:
108  case kDATE:
109  case kINTERVAL_DAY_TIME:
111  return cgen_state->llInt(constant->get_constval().bigintval);
112  default:
113  UNREACHABLE();
114  }
115  UNREACHABLE();
116  return nullptr;
117 }
int8_t tinyintval
Definition: Datum.h:73
Definition: sqltypes.h:76
bool get_is_null() const
Definition: Analyzer.h:347
#define UNREACHABLE()
Definition: Logger.h:338
int32_t intval
Definition: Datum.h:75
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
int64_t bigintval
Definition: Datum.h:76
int16_t smallintval
Definition: Datum.h:74
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:561
Definition: sqltypes.h:80
Datum get_constval() const
Definition: Analyzer.h:348
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
Definition: sqltypes.h:72

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenIsNull ( const Analyzer::UOper uoper,
const CompilationOptions co 
)
private

Definition at line 381 of file LogicalIR.cpp.

References AUTOMATIC_IR_METADATA, CgenState::castToTypeIn(), cgen_state_, CHECK, codegen(), codegenIsNullNumber(), CgenState::context_, CgenState::emitCall(), CgenState::emitExternalCall(), get_int_type(), Analyzer::UOper::get_operand(), CgenState::ir_builder_, kPOINT, spatial_type::Codegen::pointIsNullFunctionName(), and posArg().

Referenced by codegen().

382  {
384  const auto operand = uoper->get_operand();
385  if (dynamic_cast<const Analyzer::Constant*>(operand) &&
386  dynamic_cast<const Analyzer::Constant*>(operand)->get_is_null()) {
387  // for null constants, short-circuit to true
388  return llvm::ConstantInt::get(get_int_type(1, cgen_state_->context_), 1);
389  }
390  const auto& ti = operand->get_type_info();
391  CHECK(ti.is_integer() || ti.is_boolean() || ti.is_decimal() || ti.is_time() ||
392  ti.is_string() || ti.is_fp() || ti.is_array() || ti.is_geometry());
393  // if the type is inferred as non null, short-circuit to false
394  if (ti.get_notnull()) {
395  return llvm::ConstantInt::get(get_int_type(1, cgen_state_->context_), 0);
396  }
397  llvm::Value* operand_lv = codegen(operand, true, co).front();
398  // NULL-check array or geo's coords array
399  if (ti.get_type() == kPOINT && dynamic_cast<Analyzer::GeoOperator const*>(operand)) {
400  char const* const fname = spatial_type::Codegen::pointIsNullFunctionName(ti);
401  return cgen_state_->emitCall(fname, {operand_lv});
402  } else if (ti.is_array() || ti.is_geometry()) {
403  // POINT [un]compressed coord check requires custom checker and chunk iterator
404  // Non-POINT NULL geographies will have a normally encoded null coord array
405  auto fname =
406  (ti.get_type() == kPOINT) ? "point_coord_array_is_null" : "array_is_null";
408  fname, get_int_type(1, cgen_state_->context_), {operand_lv, posArg(operand)});
409  } else if (ti.is_none_encoded_string()) {
410  operand_lv = cgen_state_->ir_builder_.CreateExtractValue(operand_lv, 0);
411  operand_lv = cgen_state_->castToTypeIn(operand_lv, sizeof(int64_t) * 8);
412  }
413  return codegenIsNullNumber(operand_lv, ti);
414 }
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
static char const * pointIsNullFunctionName(SQLTypeInfo const &)
Definition: Codegen.cpp:69
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_operand() const
Definition: Analyzer.h:384
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
Definition: LogicalIR.cpp:416

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenIsNullNumber ( llvm::Value *  operand_lv,
const SQLTypeInfo ti 
)
private

Definition at line 416 of file LogicalIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, SQLTypeInfo::get_type(), CgenState::inlineIntNull(), CgenState::ir_builder_, SQLTypeInfo::is_fp(), kFLOAT, CgenState::llFp(), NULL_DOUBLE, and NULL_FLOAT.

Referenced by codegenFunctionOperNullArg(), codegenIsNull(), and codegenSkipOverflowCheckForNull().

417  {
419  if (ti.is_fp()) {
420  return cgen_state_->ir_builder_.CreateFCmp(llvm::FCmpInst::FCMP_OEQ,
421  operand_lv,
422  ti.get_type() == kFLOAT
425  }
426  return cgen_state_->ir_builder_.CreateICmp(
427  llvm::ICmpInst::ICMP_EQ, operand_lv, cgen_state_->inlineIntNull(ti));
428 }
#define NULL_DOUBLE
CgenState * cgen_state_
#define NULL_FLOAT
bool is_fp() const
Definition: sqltypes.h:573
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
#define AUTOMATIC_IR_METADATA(CGENSTATE)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenLinRegPredict ( const Analyzer::MLPredictExpr expr,
const std::shared_ptr< AbstractMLModel > &  model,
const CompilationOptions co 
)
private

Definition at line 119 of file MLPredictCodegen.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenArith(), Datum::doubleval, executor(), generated_encoded_and_casted_features(), Analyzer::MLPredictExpr::get_regressor_values(), kDOUBLE, kMULTIPLY, kONE, kPLUS, and run_benchmark_import::result.

Referenced by codegen().

122  {
124  const auto linear_reg_model =
125  std::dynamic_pointer_cast<LinearRegressionModel>(abstract_model);
126  // The parent codegen function called this function `codegenLinRegPredict`
127  // iff we had MLModelType::LINEAR_REG_PREDICT, so below is just a sanity
128  // check
129  CHECK(linear_reg_model);
130  const auto& model_coefs = linear_reg_model->getCoefs();
131  const auto& cat_feature_keys = linear_reg_model->getCatFeatureKeys();
132 
133  const auto& regressor_exprs = expr->get_regressor_values();
134 
135  const auto casted_regressor_exprs = generated_encoded_and_casted_features(
136  regressor_exprs,
137  cat_feature_keys,
138  linear_reg_model->getModelMetadata().getFeaturePermutations(),
139  executor());
140 
141  auto get_double_constant_expr = [](double const_val) {
142  Datum d;
143  d.doubleval = const_val;
144  return makeExpr<Analyzer::Constant>(SQLTypeInfo(kDOUBLE, false), false, d);
145  };
146 
147  std::shared_ptr<Analyzer::Expr> result;
148 
149  // Linear regression models are of the form
150  // y = b0 + b1*x1 + b2*x2 + ... + bn*xn
151  // Where b0 is the constant y-intercept, x1..xn are the dependent
152  // varabiles (aka regressors or predictors), and b1..bn are the
153  // regression coefficients
154 
155  for (size_t model_coef_idx = 0; model_coef_idx < model_coefs.size(); ++model_coef_idx) {
156  auto coef_value_expr = get_double_constant_expr(model_coefs[model_coef_idx]);
157  if (model_coef_idx == size_t(0)) {
158  // We have the y-intercept b0, this is not multiplied by any regressor
159  result = coef_value_expr;
160  } else {
161  // We have a term with a regressor (xi) and regression coefficient (bi)
162  const auto& casted_regressor_expr = casted_regressor_exprs[model_coef_idx - 1];
163  // Multiply regressor by coefficient
164  auto mul_expr = makeExpr<Analyzer::BinOper>(SQLTypeInfo(kDOUBLE, false),
165  false,
166  kMULTIPLY,
167  kONE,
168  coef_value_expr,
169  casted_regressor_expr);
170  // Add term to result
171  result = makeExpr<Analyzer::BinOper>(
172  SQLTypeInfo(kDOUBLE, false), false, kPLUS, kONE, result, mul_expr);
173  }
174  }
175 
176  // The following will codegen the expression tree we just created modeling
177  // the linear regression formula
178  return codegenArith(dynamic_cast<Analyzer::BinOper*>(result.get()), co);
179 }
llvm::Value * codegenArith(const Analyzer::BinOper *, const CompilationOptions &)
CgenState * cgen_state_
Definition: sqldefs.h:43
std::vector< std::shared_ptr< Analyzer::Expr > > generated_encoded_and_casted_features(const std::vector< std::shared_ptr< Analyzer::Expr >> &feature_exprs, const std::vector< std::vector< std::string >> &cat_feature_keys, const std::vector< int64_t > &feature_permutations, Executor *executor)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
Definition: sqldefs.h:74
#define CHECK(condition)
Definition: Logger.h:291
const std::vector< std::shared_ptr< Analyzer::Expr > > & get_regressor_values() const
Definition: Analyzer.h:714
Definition: Datum.h:71
double doubleval
Definition: Datum.h:78
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenLogical ( const Analyzer::BinOper bin_oper,
const CompilationOptions co 
)
private

Definition at line 299 of file LogicalIR.cpp.

References AUTOMATIC_IR_METADATA, CgenState::castToTypeIn(), cgen_state_, CHECK, codegen(), codegenLogicalShortCircuit(), CgenState::emitCall(), Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), CgenState::inlineIntNull(), CgenState::ir_builder_, IS_LOGIC, kAND, kOR, and toBool().

Referenced by codegen(), and codegenCmp().

300  {
302  const auto optype = bin_oper->get_optype();
303  CHECK(IS_LOGIC(optype));
304 
305  if (llvm::Value* short_circuit = codegenLogicalShortCircuit(bin_oper, co)) {
306  return short_circuit;
307  }
308 
309  const auto lhs = bin_oper->get_left_operand();
310  const auto rhs = bin_oper->get_right_operand();
311  auto lhs_lv = codegen(lhs, true, co).front();
312  auto rhs_lv = codegen(rhs, true, co).front();
313  const auto& ti = bin_oper->get_type_info();
314  if (ti.get_notnull()) {
315  switch (optype) {
316  case kAND:
317  return cgen_state_->ir_builder_.CreateAnd(toBool(lhs_lv), toBool(rhs_lv));
318  case kOR:
319  return cgen_state_->ir_builder_.CreateOr(toBool(lhs_lv), toBool(rhs_lv));
320  default:
321  CHECK(false);
322  }
323  }
324  CHECK(lhs_lv->getType()->isIntegerTy(1) || lhs_lv->getType()->isIntegerTy(8));
325  CHECK(rhs_lv->getType()->isIntegerTy(1) || rhs_lv->getType()->isIntegerTy(8));
326  if (lhs_lv->getType()->isIntegerTy(1)) {
327  lhs_lv = cgen_state_->castToTypeIn(lhs_lv, 8);
328  }
329  if (rhs_lv->getType()->isIntegerTy(1)) {
330  rhs_lv = cgen_state_->castToTypeIn(rhs_lv, 8);
331  }
332  switch (optype) {
333  case kAND:
334  return cgen_state_->emitCall("logical_and",
335  {lhs_lv, rhs_lv, cgen_state_->inlineIntNull(ti)});
336  case kOR:
337  return cgen_state_->emitCall("logical_or",
338  {lhs_lv, rhs_lv, cgen_state_->inlineIntNull(ti)});
339  default:
340  abort();
341  }
342 }
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
#define IS_LOGIC(X)
Definition: sqldefs.h:64
CgenState * cgen_state_
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:40
SQLOps get_optype() const
Definition: Analyzer.h:452
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
Definition: sqldefs.h:39
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455
llvm::Value * codegenLogicalShortCircuit(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:197

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenLogical ( const Analyzer::UOper uoper,
const CompilationOptions co 
)
private

Definition at line 363 of file LogicalIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), CgenState::emitCall(), Analyzer::UOper::get_operand(), Analyzer::UOper::get_optype(), Analyzer::Expr::get_type_info(), CgenState::inlineIntNull(), CgenState::ir_builder_, anonymous_namespace{LogicalIR.cpp}::is_qualified_bin_oper(), kNOT, and toBool().

364  {
366  const auto optype = uoper->get_optype();
367  CHECK_EQ(kNOT, optype);
368  const auto operand = uoper->get_operand();
369  const auto& operand_ti = operand->get_type_info();
370  CHECK(operand_ti.is_boolean());
371  const auto operand_lv = codegen(operand, true, co).front();
372  CHECK(operand_lv->getType()->isIntegerTy());
373  const bool not_null = (operand_ti.get_notnull() || is_qualified_bin_oper(operand));
374  CHECK(not_null || operand_lv->getType()->isIntegerTy(8));
375  return not_null
376  ? cgen_state_->ir_builder_.CreateNot(toBool(operand_lv))
378  "logical_not", {operand_lv, cgen_state_->inlineIntNull(operand_ti)});
379 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
bool is_qualified_bin_oper(const Analyzer::Expr *expr)
Definition: LogicalIR.cpp:356
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_operand() const
Definition: Analyzer.h:384
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:41
SQLOps get_optype() const
Definition: Analyzer.h:383

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::codegenLogicalShortCircuit ( const Analyzer::BinOper bin_oper,
const CompilationOptions co 
)
private

Definition at line 197 of file LogicalIR.cpp.

References AUTOMATIC_IR_METADATA, CgenState::castToTypeIn(), cgen_state_, codegen(), anonymous_namespace{LogicalIR.cpp}::contains_unsafe_division(), CgenState::context_, CgenState::current_func_, Analyzer::BinOper::get_left_operand(), anonymous_namespace{LogicalIR.cpp}::get_likelihood(), Analyzer::BinOper::get_optype(), Analyzer::BinOper::get_right_operand(), Analyzer::Expr::get_type_info(), anonymous_namespace{LogicalIR.cpp}::get_weight(), CgenState::inlineIntNull(), CgenState::ir_builder_, kAND, kOR, and gpu_enabled::swap().

Referenced by codegenLogical().

198  {
200  const auto optype = bin_oper->get_optype();
201  auto lhs = bin_oper->get_left_operand();
202  auto rhs = bin_oper->get_right_operand();
203 
204  if (contains_unsafe_division(rhs)) {
205  // rhs contains a possible div-by-0: short-circuit
206  } else if (contains_unsafe_division(lhs)) {
207  // lhs contains a possible div-by-0: swap and short-circuit
208  std::swap(rhs, lhs);
209  } else if (((optype == kOR && get_likelihood(lhs) > 0.90) ||
210  (optype == kAND && get_likelihood(lhs) < 0.10)) &&
211  get_weight(rhs) > 10) {
212  // short circuit if we're likely to see either (trueA || heavyB) or (falseA && heavyB)
213  } else if (((optype == kOR && get_likelihood(rhs) > 0.90) ||
214  (optype == kAND && get_likelihood(rhs) < 0.10)) &&
215  get_weight(lhs) > 10) {
216  // swap and short circuit if we're likely to see either (heavyA || trueB) or (heavyA
217  // && falseB)
218  std::swap(rhs, lhs);
219  } else {
220  // no motivation to short circuit
221  return nullptr;
222  }
223 
224  const auto& ti = bin_oper->get_type_info();
225  auto lhs_lv = codegen(lhs, true, co).front();
226 
227  // Here the linear control flow will diverge and expressions cached during the
228  // code branch code generation (currently just column decoding) are not going
229  // to be available once we're done generating the short-circuited logic.
230  // Take a snapshot of the cache with FetchCacheAnchor and restore it once
231  // the control flow converges.
233 
234  auto rhs_bb = llvm::BasicBlock::Create(
236  auto ret_bb = llvm::BasicBlock::Create(
238  llvm::BasicBlock* nullcheck_ok_bb{nullptr};
239  llvm::BasicBlock* nullcheck_fail_bb{nullptr};
240 
241  if (!ti.get_notnull()) {
242  // need lhs nullcheck before short circuiting
243  nullcheck_ok_bb = llvm::BasicBlock::Create(
244  cgen_state_->context_, "nullcheck_ok_bb", cgen_state_->current_func_);
245  nullcheck_fail_bb = llvm::BasicBlock::Create(
246  cgen_state_->context_, "nullcheck_fail_bb", cgen_state_->current_func_);
247  if (lhs_lv->getType()->isIntegerTy(1)) {
248  lhs_lv = cgen_state_->castToTypeIn(lhs_lv, 8);
249  }
250  auto lhs_nullcheck =
251  cgen_state_->ir_builder_.CreateICmpEQ(lhs_lv, cgen_state_->inlineIntNull(ti));
252  cgen_state_->ir_builder_.CreateCondBr(
253  lhs_nullcheck, nullcheck_fail_bb, nullcheck_ok_bb);
254  cgen_state_->ir_builder_.SetInsertPoint(nullcheck_ok_bb);
255  }
256 
257  auto sc_check_bb = cgen_state_->ir_builder_.GetInsertBlock();
258  auto cnst_lv = llvm::ConstantInt::get(lhs_lv->getType(), (optype == kOR));
259  // Branch to codegen rhs if NOT getting (true || rhs) or (false && rhs), likelihood of
260  // the branch is < 0.10
261  cgen_state_->ir_builder_.CreateCondBr(
262  cgen_state_->ir_builder_.CreateICmpNE(lhs_lv, cnst_lv),
263  rhs_bb,
264  ret_bb,
265  llvm::MDBuilder(cgen_state_->context_).createBranchWeights(10, 90));
266 
267  // Codegen rhs when unable to short circuit.
268  cgen_state_->ir_builder_.SetInsertPoint(rhs_bb);
269  auto rhs_lv = codegen(rhs, true, co).front();
270  if (!ti.get_notnull()) {
271  // need rhs nullcheck as well
272  if (rhs_lv->getType()->isIntegerTy(1)) {
273  rhs_lv = cgen_state_->castToTypeIn(rhs_lv, 8);
274  }
275  auto rhs_nullcheck =
276  cgen_state_->ir_builder_.CreateICmpEQ(rhs_lv, cgen_state_->inlineIntNull(ti));
277  cgen_state_->ir_builder_.CreateCondBr(rhs_nullcheck, nullcheck_fail_bb, ret_bb);
278  } else {
279  cgen_state_->ir_builder_.CreateBr(ret_bb);
280  }
281  auto rhs_codegen_bb = cgen_state_->ir_builder_.GetInsertBlock();
282 
283  if (!ti.get_notnull()) {
284  cgen_state_->ir_builder_.SetInsertPoint(nullcheck_fail_bb);
285  cgen_state_->ir_builder_.CreateBr(ret_bb);
286  }
287 
288  cgen_state_->ir_builder_.SetInsertPoint(ret_bb);
289  auto result_phi =
290  cgen_state_->ir_builder_.CreatePHI(lhs_lv->getType(), (!ti.get_notnull()) ? 3 : 2);
291  if (!ti.get_notnull()) {
292  result_phi->addIncoming(cgen_state_->inlineIntNull(ti), nullcheck_fail_bb);
293  }
294  result_phi->addIncoming(cnst_lv, sc_check_bb);
295  result_phi->addIncoming(rhs_lv, rhs_codegen_bb);
296  return result_phi;
297 }
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
CgenState * cgen_state_
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:40
SQLOps get_optype() const
Definition: Analyzer.h:452
Likelihood get_likelihood(const Analyzer::Expr *expr)
Definition: LogicalIR.cpp:79
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
Weight get_weight(const Analyzer::Expr *expr, int depth=0)
Definition: LogicalIR.cpp:119
Definition: sqldefs.h:39
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
bool contains_unsafe_division(const Analyzer::Expr *expr)
Definition: LogicalIR.cpp:26
const Expr * get_left_operand() const
Definition: Analyzer.h:455
DEVICE void swap(ARGS &&...args)
Definition: gpu_enabled.h:114

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenMod ( llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const std::string &  null_typename,
const std::string &  null_check_suffix,
const SQLTypeInfo ti 
)
private

Definition at line 598 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, CgenState::context_, CgenState::current_func_, CgenState::emitCall(), inline_int_null_val(), CgenState::ir_builder_, SQLTypeInfo::is_integer(), CgenState::llInt(), and CgenState::needs_error_check_.

Referenced by codegenIntArith().

602  {
604  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
605  CHECK(ti.is_integer());
607  // Generate control flow for division by zero error handling.
608  auto mod_ok = llvm::BasicBlock::Create(
610  auto mod_zero = llvm::BasicBlock::Create(
612  auto zero_const = llvm::ConstantInt::get(rhs_lv->getType(), 0, true);
613  cgen_state_->ir_builder_.CreateCondBr(
614  cgen_state_->ir_builder_.CreateICmp(llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
615  mod_ok,
616  mod_zero);
617  cgen_state_->ir_builder_.SetInsertPoint(mod_ok);
618  auto ret = null_typename.empty()
619  ? cgen_state_->ir_builder_.CreateSRem(lhs_lv, rhs_lv)
621  "mod_" + null_typename + null_check_suffix,
622  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
623  cgen_state_->ir_builder_.SetInsertPoint(mod_zero);
624  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt(int32_t(ErrorCode::DIV_BY_ZERO)));
625  cgen_state_->ir_builder_.SetInsertPoint(mod_ok);
626  return ret;
627 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
bool is_integer() const
Definition: sqltypes.h:567
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenMul ( const Analyzer::BinOper bin_oper,
llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const std::string &  null_typename,
const std::string &  null_check_suffix,
const SQLTypeInfo ti,
const CompilationOptions co,
bool  downscale = true 
)
private

Definition at line 361 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, checkExpressionRanges(), codegenBinOpWithOverflowForCPU(), codegenSkipOverflowCheckForNull(), CgenState::context_, CPU, CgenState::current_func_, CompilationOptions::device_type, CgenState::emitCall(), SQLTypeInfo::get_size(), inline_int_null_val(), CgenState::inlineIntMaxMin(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_timeinterval(), CgenState::llInt(), and CgenState::needs_error_check_.

Referenced by codegenIntArith().

368  {
370  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
371  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
372  llvm::Value* chosen_max{nullptr};
373  llvm::Value* chosen_min{nullptr};
374  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
375  auto need_overflow_check =
376  !checkExpressionRanges(bin_oper,
377  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
378  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
379 
380  if (need_overflow_check && co.device_type == ExecutorDeviceType::CPU) {
382  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
383  }
384 
385  llvm::BasicBlock* mul_ok{nullptr};
386  llvm::BasicBlock* mul_fail{nullptr};
387  if (need_overflow_check) {
389  mul_ok = llvm::BasicBlock::Create(
391  if (!null_check_suffix.empty()) {
392  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, mul_ok, ti);
393  }
394  mul_fail = llvm::BasicBlock::Create(
396  auto mul_check = llvm::BasicBlock::Create(
398  auto const_zero = llvm::ConstantInt::get(rhs_lv->getType(), 0, true);
399  cgen_state_->ir_builder_.CreateCondBr(
400  cgen_state_->ir_builder_.CreateICmpEQ(rhs_lv, const_zero), mul_ok, mul_check);
401  cgen_state_->ir_builder_.SetInsertPoint(mul_check);
402  auto rhs_is_negative_lv = cgen_state_->ir_builder_.CreateICmpSLT(rhs_lv, const_zero);
403  auto positive_rhs_lv = cgen_state_->ir_builder_.CreateSelect(
404  rhs_is_negative_lv, cgen_state_->ir_builder_.CreateNeg(rhs_lv), rhs_lv);
405  auto adjusted_lhs_lv = cgen_state_->ir_builder_.CreateSelect(
406  rhs_is_negative_lv, cgen_state_->ir_builder_.CreateNeg(lhs_lv), lhs_lv);
407  auto detected = cgen_state_->ir_builder_.CreateOr( // overflow
408  cgen_state_->ir_builder_.CreateICmpSGT(
409  adjusted_lhs_lv,
410  cgen_state_->ir_builder_.CreateSDiv(chosen_max, positive_rhs_lv)),
411  // underflow
412  cgen_state_->ir_builder_.CreateICmpSLT(
413  adjusted_lhs_lv,
414  cgen_state_->ir_builder_.CreateSDiv(chosen_min, positive_rhs_lv)));
415  cgen_state_->ir_builder_.CreateCondBr(detected, mul_fail, mul_ok);
416  cgen_state_->ir_builder_.SetInsertPoint(mul_ok);
417  }
418  const auto ret =
419  null_check_suffix.empty()
420  ? cgen_state_->ir_builder_.CreateMul(lhs_lv, rhs_lv)
422  "mul_" + null_typename + null_check_suffix,
423  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
424  if (need_overflow_check) {
425  cgen_state_->ir_builder_.SetInsertPoint(mul_fail);
426  cgen_state_->ir_builder_.CreateRet(
427  cgen_state_->llInt(int32_t(ErrorCode::OVERFLOW_OR_UNDERFLOW)));
428  cgen_state_->ir_builder_.SetInsertPoint(mul_ok);
429  }
430  return ret;
431 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
HOST DEVICE int get_size() const
Definition: sqltypes.h:403
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
bool is_integer() const
Definition: sqltypes.h:567
void codegenSkipOverflowCheckForNull(llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
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)
bool is_timeinterval() const
Definition: sqltypes.h:594
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
ExecutorDeviceType device_type
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool checkExpressionRanges(const Analyzer::UOper *, int64_t, int64_t)
bool is_decimal() const
Definition: sqltypes.h:570
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenOuterJoinNullPlaceholder ( const Analyzer::ColumnVar col_var,
const bool  fetch_column,
const CompilationOptions co 
)
private

Definition at line 496 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegen(), codegenColVar(), CgenState::context_, CgenState::current_func_, foundOuterJoinMatch(), Analyzer::ColumnVar::get_rte_idx(), Analyzer::Expr::get_type_info(), CgenState::ir_builder_, needCastForHashJoinLhs(), and resolveGroupedColumnReference().

Referenced by codegenColumn().

499  {
501  const auto grouped_col_lv = resolveGroupedColumnReference(col_var);
502  if (grouped_col_lv) {
503  return {grouped_col_lv};
504  }
505  const auto outer_join_args_bb = llvm::BasicBlock::Create(
506  cgen_state_->context_, "outer_join_args", cgen_state_->current_func_);
507  const auto outer_join_nulls_bb = llvm::BasicBlock::Create(
508  cgen_state_->context_, "outer_join_nulls", cgen_state_->current_func_);
509  const auto phi_bb = llvm::BasicBlock::Create(
510  cgen_state_->context_, "outer_join_phi", cgen_state_->current_func_);
511  const auto outer_join_match_lv = foundOuterJoinMatch(col_var->get_rte_idx());
512  CHECK(outer_join_match_lv);
513  cgen_state_->ir_builder_.CreateCondBr(
514  outer_join_match_lv, outer_join_args_bb, outer_join_nulls_bb);
515  const auto back_from_outer_join_bb = llvm::BasicBlock::Create(
516  cgen_state_->context_, "back_from_outer_join", cgen_state_->current_func_);
517  cgen_state_->ir_builder_.SetInsertPoint(outer_join_args_bb);
519  const auto orig_lvs = codegenColVar(col_var, fetch_column, true, co);
520  // sometimes col_var used in the join qual needs to cast its column to sync with
521  // the target join column's type which generates a code with a new bb like cast_bb
522  // if so, we need to keep that bb to correctly construct phi_bb
523  // i.e., use cast_bb instead of outer_join_args_bb for the "casted" column
524  // which is the right end point
525  const auto needs_casting_col_var = needCastForHashJoinLhs(col_var);
526  auto* cast_bb = cgen_state_->ir_builder_.GetInsertBlock();
527  cgen_state_->ir_builder_.CreateBr(phi_bb);
528  cgen_state_->ir_builder_.SetInsertPoint(outer_join_nulls_bb);
529  const auto& null_ti = col_var->get_type_info();
530  // since this represents a null constant, what value the datum object contains is
531  // meaningless we need to know what type we need to create a null constant and `null_ti`
532  // contains it
533  const auto null_constant = makeExpr<Analyzer::Constant>(null_ti, true, Datum{0});
534  auto const null_target_lvs = codegen(null_constant.get(), fetch_column, co);
535  cgen_state_->ir_builder_.CreateBr(phi_bb);
536  CHECK_EQ(orig_lvs.size(), null_target_lvs.size());
537  cgen_state_->ir_builder_.SetInsertPoint(phi_bb);
538  std::vector<llvm::Value*> target_lvs;
539  for (size_t i = 0; i < orig_lvs.size(); ++i) {
540  const auto target_type = orig_lvs[i]->getType();
541  const auto null_type = null_target_lvs[i]->getType();
542  CHECK_EQ(target_type, null_type);
543  auto target_phi = cgen_state_->ir_builder_.CreatePHI(target_type, 2);
544  const auto orig_lvs_bb = needs_casting_col_var ? cast_bb : outer_join_args_bb;
545  target_phi->addIncoming(orig_lvs[i], orig_lvs_bb);
546  target_phi->addIncoming(null_target_lvs[i], outer_join_nulls_bb);
547  target_lvs.push_back(target_phi);
548  }
549  cgen_state_->ir_builder_.CreateBr(back_from_outer_join_bb);
550  cgen_state_->ir_builder_.SetInsertPoint(back_from_outer_join_bb);
551  return target_lvs;
552 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * foundOuterJoinMatch(const size_t nesting_level) const
Definition: ColumnIR.cpp:489
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegenColVar(const Analyzer::ColumnVar *, const bool fetch_column, const bool update_query_plan, const CompilationOptions &)
Definition: ColumnIR.cpp:106
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
bool needCastForHashJoinLhs(const Analyzer::ColumnVar *rhs) const
Definition: ColumnIR.cpp:706
#define CHECK(condition)
Definition: Logger.h:291
int32_t get_rte_idx() const
Definition: Analyzer.h:202
Definition: Datum.h:71
llvm::Value * resolveGroupedColumnReference(const Analyzer::ColumnVar *)
Definition: ColumnIR.cpp:554

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenPerRowStringOper ( const Analyzer::StringOper string_oper,
const CompilationOptions co 
)

Definition at line 351 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, CHECK_GE, CHECK_LE, codegenStringFetchAndEncode(), CONCAT, CgenState::context_, CompilationOptions::device_type, CgenState::emitExternalCall(), executor(), g_cluster, get_fp_type(), get_int_type(), Analyzer::StringOper::get_kind(), Analyzer::Expr::get_type_info(), Analyzer::StringOper::getArity(), Analyzer::StringOper::getNonLiteralsArity(), getStringOpInfos(), GPU, CgenState::inlineNull(), kBIGINT, kBOOLEAN, kDATE, kDECIMAL, kDOUBLE, kFLOAT, kINT, kNUMERIC, kSMALLINT, kTIME, kTIMESTAMP, kTINYINT, CgenState::llInt(), RCONCAT, to_lower(), and toString().

Referenced by codegen().

352  {
354  CHECK_GE(expr->getArity(), 1UL);
355  const auto non_literals_arity = expr->getNonLiteralsArity();
356  CHECK_GE(non_literals_arity, 1UL);
357  CHECK_LE(non_literals_arity, 2UL);
358  const auto& return_ti = expr->get_type_info();
359  if (g_cluster && return_ti.is_dict_encoded_string()) {
360  throw std::runtime_error(
361  "Cast from none-encoded string to dictionary-encoded not supported for "
362  "distributed queries");
363  }
365  throw QueryMustRunOnCpu();
366  }
367  const auto [primary_str_lv, nullcheck_codegen] =
368  codegenStringFetchAndEncode(expr, co, 0UL, false);
369  CHECK_EQ(size_t(3), primary_str_lv.size());
370 
371  const auto string_op_infos = getStringOpInfos(expr);
372  CHECK(string_op_infos.size());
373 
374  const auto string_ops =
375  executor()->getRowSetMemoryOwner()->getStringOps(string_op_infos);
376  const int64_t string_ops_handle = reinterpret_cast<int64_t>(string_ops);
377  auto string_ops_handle_lv = cgen_state_->llInt(string_ops_handle);
378 
379  if (!return_ti.is_string()) {
380  CHECK_GE(non_literals_arity, 1UL);
381  CHECK_LE(non_literals_arity, 2UL);
382  std::vector<llvm::Value*> string_oper_lvs;
383  if (non_literals_arity == 1UL) {
384  string_oper_lvs = {primary_str_lv[1], primary_str_lv[2], string_ops_handle_lv};
385  } else {
386  const auto [secondary_str_lv, secondary_nullcheck_codegen] =
387  codegenStringFetchAndEncode(expr, co, 1UL, false);
388  CHECK_EQ(size_t(3), secondary_str_lv.size());
389  string_oper_lvs = {primary_str_lv[1],
390  primary_str_lv[2],
391  secondary_str_lv[1],
392  secondary_str_lv[2],
393  string_ops_handle_lv};
394  }
395  const auto return_type = return_ti.get_type();
396  std::string fn_call = non_literals_arity == 1UL
397  ? "apply_numeric_string_ops_"
398  : "apply_multi_input_numeric_string_ops_";
399  switch (return_type) {
400  case kBOOLEAN: {
401  fn_call += "bool";
402  break;
403  }
404  case kTINYINT:
405  case kSMALLINT:
406  case kINT:
407  case kBIGINT:
408  case kFLOAT:
409  case kDOUBLE: {
410  fn_call += to_lower(toString(return_type));
411  break;
412  }
413  case kNUMERIC:
414  case kDECIMAL:
415  case kTIME:
416  case kTIMESTAMP:
417  case kDATE: {
418  fn_call += "bigint";
419  break;
420  }
421  default: {
422  throw std::runtime_error("Unimplemented type for string-to-numeric translation");
423  }
424  }
425  const auto logical_size = return_ti.get_logical_size() * 8;
426  auto llvm_return_type = return_ti.is_fp()
427  ? get_fp_type(logical_size, cgen_state_->context_)
428  : get_int_type(logical_size, cgen_state_->context_);
429  auto ret = cgen_state_->emitExternalCall(fn_call, llvm_return_type, string_oper_lvs);
430  if (nullcheck_codegen) {
431  ret = nullcheck_codegen->finalize(cgen_state_->inlineNull(return_ti), ret);
432  }
433  return ret;
434  }
435 
436  // If here we are outputing a string dictionary column
437  CHECK(return_ti.is_dict_encoded_string());
438  const int64_t dest_string_proxy_handle =
439  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
440  return_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true));
441  auto dest_string_proxy_handle_lv = cgen_state_->llInt(dest_string_proxy_handle);
442  if (non_literals_arity == 1UL) {
443  std::vector<llvm::Value*> string_oper_lvs{primary_str_lv[1],
444  primary_str_lv[2],
445  string_ops_handle_lv,
446  dest_string_proxy_handle_lv};
447 
448  auto ret = cgen_state_->emitExternalCall("apply_string_ops_and_encode",
450  string_oper_lvs);
451  if (nullcheck_codegen) {
452  ret = nullcheck_codegen->finalize(cgen_state_->inlineNull(return_ti), ret);
453  }
454  return ret;
455  } else {
456  // For now only CONCAT is supported, which takes up to 2 non-literal string
457  // arguments. In the future (likely when we can codegen the StringOps to enable
458  // generic, multi-branch execution rather than linear chains of functors as we do
459  // today), we will generalize this to functions that take
460  // any number of string and numeric non-literal arguments, in which case
461  // we will need to make apply_multi_input_string_ops_and_encode take
462  // a vector of arguments. For now, however, expecting exactly 2 arguments
463  // suffices.
464  CHECK_EQ(non_literals_arity, 2UL);
465  CHECK(expr->get_kind() == SqlStringOpKind::CONCAT ||
466  expr->get_kind() == SqlStringOpKind::RCONCAT);
467  const auto [secondary_str_lv, secondary_nullcheck_codegen] =
468  codegenStringFetchAndEncode(expr, co, 1UL, false);
469  CHECK_EQ(size_t(3), secondary_str_lv.size());
470  std::vector<llvm::Value*> string_oper_lvs{primary_str_lv[1],
471  primary_str_lv[2],
472  secondary_str_lv[1],
473  secondary_str_lv[2],
474  string_ops_handle_lv,
475  dest_string_proxy_handle_lv};
476  auto ret = cgen_state_->emitExternalCall("apply_multi_input_string_ops_and_encode",
478  string_oper_lvs);
479  if (secondary_nullcheck_codegen) {
480  ret =
481  secondary_nullcheck_codegen->finalize(cgen_state_->inlineNull(return_ti), ret);
482  }
483  if (nullcheck_codegen) {
484  ret = nullcheck_codegen->finalize(cgen_state_->inlineNull(return_ti), ret);
485  }
486  return ret;
487  }
488 }
std::string to_lower(const std::string &str)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Definition: sqltypes.h:76
CgenState * cgen_state_
#define CHECK_GE(x, y)
Definition: Logger.h:306
llvm::Type * get_fp_type(const int width, llvm::LLVMContext &context)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string toString(const Executor::ExtModuleKinds &kind)
Definition: Execute.h:1703
llvm::Constant * inlineNull(const SQLTypeInfo &)
Definition: CgenState.cpp:116
ExecutorDeviceType device_type
std::vector< StringOps_Namespace::StringOpInfo > getStringOpInfos(const Analyzer::StringOper *expr)
Definition: sqltypes.h:80
#define CHECK_LE(x, y)
Definition: Logger.h:304
std::pair< std::vector< llvm::Value * >, std::unique_ptr< CodeGenerator::NullCheckCodegen > > codegenStringFetchAndEncode(const Analyzer::StringOper *expr, const CompilationOptions &co, const size_t arg_idx, const bool codegen_nullcheck)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool g_cluster
Definition: sqltypes.h:72
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenPseudoStringOper ( const Analyzer::ColumnVar expr,
const std::vector< StringOps_Namespace::StringOpInfo > &  string_op_infos,
const CompilationOptions co 
)

Definition at line 557 of file StringOpsIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, codegen(), StringDictionaryTranslationMgr::codegen(), Data_Namespace::CPU_LEVEL, CompilationOptions::device_type, executor(), Analyzer::Expr::get_type_info(), SQLTypeInfo::getStringDictKey(), GPU, Data_Namespace::GPU_LEVEL, and CgenState::moveStringDictionaryTranslationMgr().

Referenced by HashJoin::codegenColOrStringOper().

560  {
562  const auto& expr_ti = expr->get_type_info();
563  const auto& dict_id = expr_ti.getStringDictKey();
564 
565  auto string_dictionary_translation_mgr =
566  std::make_unique<StringDictionaryTranslationMgr>(
567  dict_id,
568  dict_id,
569  false, // translate_intersection_only
570  expr->get_type_info(),
571  string_op_infos,
574  executor()->deviceCount(co.device_type),
575  executor(),
576  executor()->getDataMgr(),
577  false /* delay_translation */);
578 
579  auto str_id_lv = codegen(expr, true /* fetch_column */, co);
580  CHECK_EQ(size_t(1), str_id_lv.size());
581 
582  return cgen_state_
583  ->moveStringDictionaryTranslationMgr(std::move(string_dictionary_translation_mgr))
584  ->codegen(str_id_lv[0], expr_ti, true /* add_nullcheck */, co);
585 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const StringDictionaryTranslationMgr * moveStringDictionaryTranslationMgr(std::unique_ptr< const StringDictionaryTranslationMgr > &&str_dict_translation_mgr)
Definition: CgenState.h:199
llvm::Value * codegen(llvm::Value *str_id_input, const SQLTypeInfo &input_ti, const bool add_nullcheck, const CompilationOptions &co) const
const shared::StringDictKey & getStringDictKey() const
Definition: sqltypes.h:1057
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenQualifierCmp ( const SQLOps  optype,
const SQLQualifier  qualifier,
std::vector< llvm::Value * >  lhs_lvs,
const Analyzer::Expr rhs,
const CompilationOptions co 
)
private

Definition at line 589 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, CHECK_NE, codegen(), CgenState::context_, CompilationOptions::device_type, CgenState::emitExternalCall(), executor(), g_cluster, g_enable_watchdog, get_int_type(), Analyzer::Expr::get_type_info(), GPU, anonymous_namespace{CompareIR.cpp}::icmp_arr_name(), CgenState::inlineIntNull(), kANY, kCAST, kDOUBLE, kENCODING_DICT, kENCODING_NONE, kONE, CgenState::llInt(), numeric_type_name(), and posArg().

Referenced by codegenCmp().

593  {
595  const auto& rhs_ti = rhs->get_type_info();
596  const Analyzer::Expr* arr_expr{rhs};
597  if (dynamic_cast<const Analyzer::UOper*>(rhs)) {
598  const auto cast_arr = static_cast<const Analyzer::UOper*>(rhs);
599  CHECK_EQ(kCAST, cast_arr->get_optype());
600  arr_expr = cast_arr->get_operand();
601  }
602  const auto& arr_ti = arr_expr->get_type_info();
603  const auto& elem_ti = arr_ti.get_elem_type();
604  auto rhs_lvs = codegen(arr_expr, true, co);
605  CHECK_NE(kONE, qualifier);
606  std::string fname{std::string("array_") + (qualifier == kANY ? "any" : "all") + "_" +
607  icmp_arr_name(optype)};
608  const auto& target_ti = rhs_ti.get_elem_type();
609  const bool is_real_string{target_ti.is_string() &&
610  target_ti.get_compression() != kENCODING_DICT};
611  if (is_real_string) {
612  if (g_cluster) {
613  throw std::runtime_error(
614  "Comparison between a dictionary-encoded and a none-encoded string not "
615  "supported for distributed queries");
616  }
617  if (g_enable_watchdog) {
618  throw WatchdogException(
619  "Comparison between a dictionary-encoded and a none-encoded string would be "
620  "slow");
621  }
623  throw QueryMustRunOnCpu();
624  }
625  CHECK_EQ(kENCODING_NONE, target_ti.get_compression());
626  fname += "_str";
627  }
628  if (elem_ti.is_integer() || elem_ti.is_boolean() || elem_ti.is_string() ||
629  elem_ti.is_decimal()) {
630  fname += ("_" + numeric_type_name(elem_ti));
631  } else {
632  CHECK(elem_ti.is_fp());
633  fname += elem_ti.get_type() == kDOUBLE ? "_double" : "_float";
634  }
635  if (is_real_string) {
636  CHECK_EQ(size_t(3), lhs_lvs.size());
638  fname,
640  {rhs_lvs.front(),
641  posArg(arr_expr),
642  lhs_lvs[1],
643  lhs_lvs[2],
644  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
645  elem_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true))),
646  cgen_state_->inlineIntNull(elem_ti)});
647  }
648  if (target_ti.is_integer() || target_ti.is_boolean() || target_ti.is_string() ||
649  target_ti.is_decimal()) {
650  fname += ("_" + numeric_type_name(target_ti));
651  } else {
652  CHECK(target_ti.is_fp());
653  fname += target_ti.get_type() == kDOUBLE ? "_double" : "_float";
654  }
656  fname,
658  {rhs_lvs.front(),
659  posArg(arr_expr),
660  lhs_lvs.front(),
661  elem_ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(elem_ti))
662  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(elem_ti))});
663 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
Definition: sqldefs.h:51
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string icmp_arr_name(const SQLOps op_type)
Definition: CompareIR.cpp:64
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define CHECK_NE(x, y)
Definition: Logger.h:302
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool g_enable_watchdog
Definition: sqldefs.h:74
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqldefs.h:74
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool g_cluster
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenRowId ( const Analyzer::ColumnVar col_var,
const CompilationOptions co 
)
private

Definition at line 391 of file ColumnIR.cpp.

References anonymous_namespace{ColumnIR.cpp}::adjusted_range_table_index(), AUTOMATIC_IR_METADATA, Datum::bigintval, cgen_state_, CHECK, CHECK_EQ, codegen(), executor(), CgenState::frag_offsets_, get_arg_by_name(), Analyzer::ColumnVar::get_rte_idx(), Analyzer::ColumnVar::getTableKey(), CgenState::ir_builder_, kBIGINT, kENCODING_NONE, CgenState::llInt(), posArg(), and CgenState::row_func_.

Referenced by codegenColVar().

392  {
394  const auto offset_lv = cgen_state_->frag_offsets_[adjusted_range_table_index(col_var)];
395  llvm::Value* start_rowid_lv{nullptr};
396  const auto& table_generation = executor()->getTableGeneration(col_var->getTableKey());
397  if (table_generation.start_rowid > 0) {
398  // Handle the multi-node case: each leaf receives a start rowid used
399  // to offset the local rowid and generate a cluster-wide unique rowid.
400  Datum d;
401  d.bigintval = table_generation.start_rowid;
402  const auto start_rowid = makeExpr<Analyzer::Constant>(kBIGINT, false, d);
403  const auto start_rowid_lvs = codegen(start_rowid.get(), kENCODING_NONE, {}, co);
404  CHECK_EQ(size_t(1), start_rowid_lvs.size());
405  start_rowid_lv = start_rowid_lvs.front();
406  }
407  auto rowid_lv = posArg(col_var);
408  if (offset_lv) {
409  rowid_lv = cgen_state_->ir_builder_.CreateAdd(rowid_lv, offset_lv);
410  } else if (col_var->get_rte_idx() > 0) {
411  auto frag_off_ptr = get_arg_by_name(cgen_state_->row_func_, "frag_row_off");
412  auto input_off_ptr = cgen_state_->ir_builder_.CreateGEP(
413  frag_off_ptr->getType()->getScalarType()->getPointerElementType(),
414  frag_off_ptr,
415  cgen_state_->llInt(int32_t(col_var->get_rte_idx())));
416  auto rowid_offset_lv = cgen_state_->ir_builder_.CreateLoad(
417  input_off_ptr->getType()->getPointerElementType(), input_off_ptr);
418  rowid_lv = cgen_state_->ir_builder_.CreateAdd(rowid_lv, rowid_offset_lv);
419  }
420  if (table_generation.start_rowid > 0) {
421  CHECK(start_rowid_lv);
422  rowid_lv = cgen_state_->ir_builder_.CreateAdd(rowid_lv, start_rowid_lv);
423  }
424  return rowid_lv;
425 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
llvm::Function * row_func_
Definition: CgenState.h:374
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:168
int64_t bigintval
Definition: Datum.h:76
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
std::vector< llvm::Value * > frag_offsets_
Definition: CgenState.h:393
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int32_t get_rte_idx() const
Definition: Analyzer.h:202
Definition: Datum.h:71
int adjusted_range_table_index(const Analyzer::ColumnVar *col_var)
Definition: ColumnIR.cpp:88
shared::TableKey getTableKey() const
Definition: Analyzer.h:199
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::codegenSkipOverflowCheckForNull ( llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
llvm::BasicBlock *  no_overflow_bb,
const SQLTypeInfo ti 
)
private

Definition at line 345 of file ArithmeticIR.cpp.

References cgen_state_, codegenIsNullNumber(), CgenState::context_, CgenState::current_func_, and CgenState::ir_builder_.

Referenced by codegenAdd(), codegenBinOpWithOverflowForCPU(), codegenDiv(), codegenMul(), codegenSub(), and codegenUMinus().

348  {
349  const auto lhs_is_null_lv = codegenIsNullNumber(lhs_lv, ti);
350  const auto has_null_operand_lv =
351  rhs_lv ? cgen_state_->ir_builder_.CreateOr(lhs_is_null_lv,
352  codegenIsNullNumber(rhs_lv, ti))
353  : lhs_is_null_lv;
354  auto operands_not_null = llvm::BasicBlock::Create(
355  cgen_state_->context_, "operands_not_null", cgen_state_->current_func_);
356  cgen_state_->ir_builder_.CreateCondBr(
357  has_null_operand_lv, no_overflow_bb, operands_not_null);
358  cgen_state_->ir_builder_.SetInsertPoint(operands_not_null);
359 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
Definition: LogicalIR.cpp:416

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenStrCmp ( const SQLOps  optype,
const SQLQualifier  qualifier,
const std::shared_ptr< Analyzer::Expr lhs,
const std::shared_ptr< Analyzer::Expr rhs,
const CompilationOptions co 
)
private

Definition at line 372 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenDictStrCmp(), get_null_check_suffix(), and kENCODING_DICT.

Referenced by codegenCmp().

376  {
378  const auto lhs_ti = lhs->get_type_info();
379  const auto rhs_ti = rhs->get_type_info();
380 
381  CHECK(lhs_ti.is_string());
382  CHECK(rhs_ti.is_string());
383 
384  const auto null_check_suffix = get_null_check_suffix(lhs_ti, rhs_ti);
385  if (lhs_ti.get_compression() == kENCODING_DICT &&
386  rhs_ti.get_compression() == kENCODING_DICT) {
387  if (lhs_ti.getStringDictKey() == rhs_ti.getStringDictKey()) {
388  // Both operands share a dictionary
389  // check if query is trying to compare a column against literal
390  auto ir = codegenDictStrCmp(lhs, rhs, optype, co);
391  if (ir) {
392  return ir;
393  }
394  } else {
395  // Both operands don't share a dictionary
396  return nullptr;
397  }
398  }
399  return nullptr;
400 }
CgenState * cgen_state_
llvm::Value * codegenDictStrCmp(const std::shared_ptr< Analyzer::Expr >, const std::shared_ptr< Analyzer::Expr >, const SQLOps, const CompilationOptions &co)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1661
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::pair< std::vector< llvm::Value * >, std::unique_ptr< CodeGenerator::NullCheckCodegen > > CodeGenerator::codegenStringFetchAndEncode ( const Analyzer::StringOper expr,
const CompilationOptions co,
const size_t  arg_idx,
const bool  codegen_nullcheck 
)
private

Definition at line 302 of file StringOpsIR.cpp.

References cgen_state_, CHECK, CHECK_EQ, CHECK_LT, codegen(), CgenState::context_, createStringViewStructType(), CgenState::emitExternalCall(), executor(), executor_, Analyzer::Expr::get_type_info(), Analyzer::StringOper::getArg(), Analyzer::StringOper::getArity(), CgenState::ir_builder_, kENCODING_DICT, kTEXT, and CgenState::llInt().

Referenced by codegenPerRowStringOper().

305  {
306  CHECK_LT(arg_idx, expr->getArity());
307  const auto& arg_ti = expr->getArg(arg_idx)->get_type_info();
308 
309  auto primary_str_lv = codegen(expr->getArg(arg_idx), true, co);
310  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
311  if (primary_str_lv.size() != 3 && arg_ti.is_dict_encoded_string()) {
312  // If this is the case we should have a transient dictionary from a previous op
313  // We can't use the dictionary values without decoding as this op occurs directly
314  // inline on top of whatever operation created the transient dictionary
315  CHECK_EQ(size_t(1), primary_str_lv.size());
316  const bool is_nullable = !arg_ti.get_notnull();
317  if (codegen_nullcheck && is_nullable) {
318  const auto decoded_input_ti = SQLTypeInfo(kTEXT, is_nullable, kENCODING_DICT);
319  nullcheck_codegen = std::make_unique<CodeGenerator::NullCheckCodegen>(
320  cgen_state_,
321  executor_,
322  primary_str_lv[0],
323  decoded_input_ti,
324  "transient_dict_per_row_nullcheck");
325  }
326  const auto sdp_ptr = reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
327  arg_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true));
328  const auto string_view =
329  cgen_state_->emitExternalCall("string_decompress",
331  {primary_str_lv[0], cgen_state_->llInt(sdp_ptr)});
332  primary_str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(string_view, 0));
333  primary_str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(string_view, 1));
334  primary_str_lv.back() = cgen_state_->ir_builder_.CreateTrunc(
335  primary_str_lv.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
336  } else if (primary_str_lv.size() == 1 and arg_ti.is_none_encoded_string()) {
337  // real (not dictionary-encoded) strings
338  CHECK(primary_str_lv[0]->getType()->isPointerTy());
339  const auto none_enc_string = cgen_state_->ir_builder_.CreateLoad(
340  primary_str_lv[0]->getType()->getPointerElementType(), primary_str_lv[0]);
341  primary_str_lv.push_back(
342  cgen_state_->ir_builder_.CreateExtractValue(none_enc_string, 0));
343  primary_str_lv.push_back(cgen_state_->ir_builder_.CreateTrunc(
344  cgen_state_->ir_builder_.CreateExtractValue(none_enc_string, 1),
345  llvm::Type::getInt32Ty(cgen_state_->context_)));
346  }
347  CHECK_EQ(size_t(3), primary_str_lv.size());
348  return std::make_pair(primary_str_lv, std::move(nullcheck_codegen));
349 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
size_t getArity() const
Definition: Analyzer.h:1674
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
Executor * executor_
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
#define CHECK_LT(x, y)
Definition: Logger.h:303
Definition: sqltypes.h:79
llvm::StructType * createStringViewStructType()
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
const Expr * getArg(const size_t i) const
Definition: Analyzer.h:1688
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenSub ( const Analyzer::BinOper bin_oper,
llvm::Value *  lhs_lv,
llvm::Value *  rhs_lv,
const std::string &  null_typename,
const std::string &  null_check_suffix,
const SQLTypeInfo ti,
const CompilationOptions co 
)
private

Definition at line 281 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, checkExpressionRanges(), codegenBinOpWithOverflowForCPU(), codegenSkipOverflowCheckForNull(), CgenState::context_, CPU, CgenState::current_func_, CompilationOptions::device_type, CgenState::emitCall(), SQLTypeInfo::get_size(), inline_int_null_val(), CgenState::inlineIntMaxMin(), CgenState::ir_builder_, SQLTypeInfo::is_decimal(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_timeinterval(), CgenState::llInt(), and CgenState::needs_error_check_.

Referenced by codegenIntArith().

287  {
289  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
290  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
291  llvm::Value* chosen_max{nullptr};
292  llvm::Value* chosen_min{nullptr};
293  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
294  auto need_overflow_check =
295  !checkExpressionRanges(bin_oper,
296  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
297  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
298 
299  if (need_overflow_check && co.device_type == ExecutorDeviceType::CPU) {
301  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
302  }
303 
304  llvm::BasicBlock* sub_ok{nullptr};
305  llvm::BasicBlock* sub_fail{nullptr};
306  if (need_overflow_check) {
308  sub_ok = llvm::BasicBlock::Create(
310  if (!null_check_suffix.empty()) {
311  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, sub_ok, ti);
312  }
313  sub_fail = llvm::BasicBlock::Create(
315  llvm::Value* detected{nullptr};
316  auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0, true);
317  auto overflow = cgen_state_->ir_builder_.CreateAnd(
318  cgen_state_->ir_builder_.CreateICmpSLT(
319  rhs_lv, const_zero), // sub going up, check the max
320  cgen_state_->ir_builder_.CreateICmpSGT(
321  lhs_lv, cgen_state_->ir_builder_.CreateAdd(chosen_max, rhs_lv)));
322  auto underflow = cgen_state_->ir_builder_.CreateAnd(
323  cgen_state_->ir_builder_.CreateICmpSGT(
324  rhs_lv, const_zero), // sub going down, check the min
325  cgen_state_->ir_builder_.CreateICmpSLT(
326  lhs_lv, cgen_state_->ir_builder_.CreateAdd(chosen_min, rhs_lv)));
327  detected = cgen_state_->ir_builder_.CreateOr(overflow, underflow);
328  cgen_state_->ir_builder_.CreateCondBr(detected, sub_fail, sub_ok);
329  cgen_state_->ir_builder_.SetInsertPoint(sub_ok);
330  }
331  auto ret = null_check_suffix.empty()
332  ? cgen_state_->ir_builder_.CreateSub(lhs_lv, rhs_lv)
334  "sub_" + null_typename + null_check_suffix,
335  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
336  if (need_overflow_check) {
337  cgen_state_->ir_builder_.SetInsertPoint(sub_fail);
338  cgen_state_->ir_builder_.CreateRet(
339  cgen_state_->llInt(int32_t(ErrorCode::OVERFLOW_OR_UNDERFLOW)));
340  cgen_state_->ir_builder_.SetInsertPoint(sub_ok);
341  }
342  return ret;
343 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
HOST DEVICE int get_size() const
Definition: sqltypes.h:403
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
bool is_integer() const
Definition: sqltypes.h:567
void codegenSkipOverflowCheckForNull(llvm::Value *lhs_lv, llvm::Value *rhs_lv, llvm::BasicBlock *no_overflow_bb, const SQLTypeInfo &ti)
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)
bool is_timeinterval() const
Definition: sqltypes.h:594
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
ExecutorDeviceType device_type
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool checkExpressionRanges(const Analyzer::UOper *, int64_t, int64_t)
bool is_decimal() const
Definition: sqltypes.h:570
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenTreeRegPredict ( const Analyzer::MLPredictExpr expr,
const std::shared_ptr< AbstractTreeModel > &  tree_model,
const CompilationOptions co 
)
private

Definition at line 181 of file MLPredictCodegen.cpp.

References cgen_state_, CHECK_EQ, codegen(), TreeModelPredictionMgr::codegen(), Data_Namespace::CPU_LEVEL, DEBUG_TIMER, CompilationOptions::device_type, executor(), generated_encoded_and_casted_features(), Analyzer::MLPredictExpr::get_regressor_values(), GPU, Data_Namespace::GPU_LEVEL, CgenState::moveTreeModelPredictionMgr(), threading_serial::parallel_for(), RANDOM_FOREST_REG, and VLOG.

Referenced by codegen().

184  {
185 #ifdef HAVE_ONEDAL
186  const int64_t num_trees = static_cast<int64_t>(tree_model->getNumTrees());
187  const auto& regressor_exprs = expr->get_regressor_values();
188  const auto& cat_feature_keys = tree_model->getCatFeatureKeys();
189  const auto casted_regressor_exprs = generated_encoded_and_casted_features(
190  regressor_exprs,
191  cat_feature_keys,
192  tree_model->getModelMetadata().getFeaturePermutations(),
193  executor());
194  // We cast all regressors to double for simplicity and to match
195  // how feature filters are stored in the tree model.
196  // Null checks are handled further down in the generated kernel
197  // in the runtime function itself
198 
199  std::vector<llvm::Value*> regressor_values;
200  for (const auto& casted_regressor_expr : casted_regressor_exprs) {
201  regressor_values.emplace_back(codegen(casted_regressor_expr.get(), false, co)[0]);
202  }
203 
204  // First build tables, i.e. vectors of DecisionTreeEntry, for each tree
205  std::vector<std::vector<DecisionTreeEntry>> decision_trees(num_trees);
206  {
207  auto tree_build_timer = DEBUG_TIMER("Tree Visitors Dispatched");
208  tbb::parallel_for(tbb::blocked_range<int64_t>(0, num_trees),
209  [&](const tbb::blocked_range<int64_t>& r) {
210  const auto start_tree_idx = r.begin();
211  const auto end_tree_idx = r.end();
212  for (int64_t tree_idx = start_tree_idx; tree_idx < end_tree_idx;
213  ++tree_idx) {
214  TreeModelVisitor tree_visitor(decision_trees[tree_idx]);
215  tree_model->traverseDF(tree_idx, tree_visitor);
216  }
217  });
218  }
219 
220  // Next, compute prefix-sum offset such that decision_tree_offsets[k]
221  // specifies the starting offset of tree k relative to tree 0, and
222  // decision_tree_offsets[k+1] specifies the last entry + 1 of tree
223  // k relative to tree 0
224  std::vector<int64_t> decision_tree_offsets(num_trees + 1);
225  decision_tree_offsets[0] = 0;
226  for (int64_t tree_idx = 0; tree_idx < num_trees; ++tree_idx) {
227  decision_tree_offsets[tree_idx + 1] =
228  decision_tree_offsets[tree_idx] +
229  static_cast<int64_t>(decision_trees[tree_idx].size());
230  }
231 
232  VLOG(1) << tree_model->getModelTypeString() << " model has " << num_trees
233  << " trees and " << decision_tree_offsets[num_trees] << " total entries.";
234 
235  // Finally, go back through each tree and adjust all left and right child idx entries
236  // such that such values are global relative to the start of tree 0. This will allow
237  // the downstream code-generated kernel to be able treat these child idx entries as
238  // as absolute offsets from the base pointer for all trees, rather than computing such
239  // an offset on the fly
240  {
241  auto tree_offset_correction_timer = DEBUG_TIMER("Tree Offsets Corrected");
243  tbb::blocked_range<int64_t>(1, num_trees),
244  [&](const tbb::blocked_range<int64_t>& r) {
245  const auto start_tree_idx = r.begin();
246  const auto end_tree_idx = r.end();
247  for (int64_t tree_idx = start_tree_idx; tree_idx < end_tree_idx; ++tree_idx) {
248  const int64_t start_offset = decision_tree_offsets[tree_idx];
249  auto& decision_tree = decision_trees[tree_idx];
250  const int64_t num_tree_entries = static_cast<int64_t>(decision_tree.size());
251  CHECK_EQ(num_tree_entries,
252  decision_tree_offsets[tree_idx + 1] - start_offset);
253  for (int64_t decision_entry_idx = 0; decision_entry_idx < num_tree_entries;
254  ++decision_entry_idx) {
255  if (decision_tree[decision_entry_idx].isSplitNode()) {
256  decision_tree[decision_entry_idx].left_child_row_idx += start_offset;
257  decision_tree[decision_entry_idx].right_child_row_idx += start_offset;
258  }
259  }
260  }
261  });
262  }
263 
264  {
265  auto tree_model_prediction_mgr_timer =
266  DEBUG_TIMER("TreeModelPredictionMgr generation and codegen");
267  // TreeModelPredictionMgr copies the decision trees and offsets to host
268  // buffers in RowSetMemoryOwner and onto each GPU if the query is running
269  // on GPU, and takes care of the tree traversal codegen itself
270 
271  const bool compute_avg = tree_model->getModelType() == MLModelType::RANDOM_FOREST_REG;
272  auto tree_model_prediction_mgr = std::make_unique<TreeModelPredictionMgr>(
275  executor(),
276  decision_trees,
277  decision_tree_offsets,
278  compute_avg);
279 
280  return cgen_state_->moveTreeModelPredictionMgr(std::move(tree_model_prediction_mgr))
281  ->codegen(regressor_values, co);
282  }
283 #else
284  throw std::runtime_error("OneDAL not available.");
285 #endif
286 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Value * codegen(const std::vector< llvm::Value * > &regressor_inputs, const CompilationOptions &co) const
std::vector< std::shared_ptr< Analyzer::Expr > > generated_encoded_and_casted_features(const std::vector< std::shared_ptr< Analyzer::Expr >> &feature_exprs, const std::vector< std::vector< std::string >> &cat_feature_keys, const std::vector< int64_t > &feature_permutations, Executor *executor)
const TreeModelPredictionMgr * moveTreeModelPredictionMgr(std::unique_ptr< const TreeModelPredictionMgr > &&tree_model_prediction_mgr)
Definition: CgenState.h:205
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
void parallel_for(const blocked_range< Int > &range, const Body &body, const Partitioner &p=Partitioner())
#define DEBUG_TIMER(name)
Definition: Logger.h:412
const std::vector< std::shared_ptr< Analyzer::Expr > > & get_regressor_values() const
Definition: Analyzer.h:714
#define VLOG(n)
Definition: Logger.h:388
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenUMinus ( const Analyzer::UOper uoper,
const CompilationOptions co 
)
private

Definition at line 654 of file ArithmeticIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, checkExpressionRanges(), codegen(), codegenSkipOverflowCheckForNull(), CgenState::context_, CgenState::current_func_, CgenState::emitCall(), Analyzer::UOper::get_operand(), Analyzer::UOper::get_optype(), Analyzer::Expr::get_type_info(), CgenState::inlineFpNull(), CgenState::inlineIntMaxMin(), CgenState::inlineIntNull(), CgenState::ir_builder_, kUMINUS, CgenState::llInt(), CgenState::needs_error_check_, and numeric_type_name().

Referenced by codegen().

655  {
657  CHECK_EQ(uoper->get_optype(), kUMINUS);
658  const auto operand_lv = codegen(uoper->get_operand(), true, co).front();
659  const auto& ti = uoper->get_type_info();
660  llvm::Value* chosen_max{nullptr};
661  llvm::Value* chosen_min{nullptr};
662  bool need_overflow_check = false;
663  if (ti.is_integer() || ti.is_decimal() || ti.is_timeinterval()) {
664  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
665  need_overflow_check = !checkExpressionRanges(
666  uoper,
667  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
668  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
669  }
670  llvm::BasicBlock* uminus_ok{nullptr};
671  llvm::BasicBlock* uminus_fail{nullptr};
672  if (need_overflow_check) {
674  uminus_ok = llvm::BasicBlock::Create(
676  if (!ti.get_notnull()) {
677  codegenSkipOverflowCheckForNull(operand_lv, nullptr, uminus_ok, ti);
678  }
679  uminus_fail = llvm::BasicBlock::Create(
680  cgen_state_->context_, "uminus_fail", cgen_state_->current_func_);
681  auto const_min = llvm::ConstantInt::get(
682  operand_lv->getType(),
683  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
684  true);
685  auto overflow = cgen_state_->ir_builder_.CreateICmpEQ(operand_lv, const_min);
686  cgen_state_->ir_builder_.CreateCondBr(overflow, uminus_fail, uminus_ok);
687  cgen_state_->ir_builder_.SetInsertPoint(uminus_ok);
688  }
689  auto ret =
690  ti.get_notnull()
691  ? (ti.is_fp() ? cgen_state_->ir_builder_.CreateFNeg(operand_lv)
692  : cgen_state_->ir_builder_.CreateNeg(operand_lv))
694  "uminus_" + numeric_type_name(ti) + "_nullable",
695  {operand_lv,
696  ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(ti))
697  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(ti))});
698  if (need_overflow_check) {
699  cgen_state_->ir_builder_.SetInsertPoint(uminus_fail);
700  cgen_state_->ir_builder_.CreateRet(
701  cgen_state_->llInt(int32_t(ErrorCode::OVERFLOW_OR_UNDERFLOW)));
702  cgen_state_->ir_builder_.SetInsertPoint(uminus_ok);
703  }
704  return ret;
705 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
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:65
bool needs_error_check_
Definition: CgenState.h:405
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_operand() const
Definition: Analyzer.h:384
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
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:121
SQLOps get_optype() const
Definition: Analyzer.h:383
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenUnnest ( const Analyzer::UOper uoper,
const CompilationOptions co 
)
private

Definition at line 20 of file ArrayIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, codegen(), and Analyzer::UOper::get_operand().

Referenced by codegen().

21  {
23  return codegen(uoper->get_operand(), true, co).front();
24 }
CgenState * cgen_state_
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
const Expr * get_operand() const
Definition: Analyzer.h:384

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector< llvm::Value * > CodeGenerator::codegenVariableLengthStringColVar ( llvm::Value *  col_byte_stream,
llvm::Value *  pos_arg 
)
private

Definition at line 377 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::context_, createStringViewStructType(), CgenState::emitExternalCall(), and CgenState::ir_builder_.

Referenced by codegenColVar().

379  {
381  // real (not dictionary-encoded) strings; store the pointer to the payload
382  auto* const string_view = cgen_state_->emitExternalCall(
383  "string_decode", createStringViewStructType(), {col_byte_stream, pos_arg});
384  auto* str_lv = cgen_state_->ir_builder_.CreateExtractValue(string_view, 0);
385  auto* len_lv = cgen_state_->ir_builder_.CreateExtractValue(string_view, 1);
386  len_lv = cgen_state_->ir_builder_.CreateTrunc(
387  len_lv, llvm::Type::getInt32Ty(cgen_state_->context_));
388  return {string_view, str_lv, len_lv};
389 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
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)
Definition: CgenState.cpp:395
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::StructType * createStringViewStructType()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenWidthBucketExpr ( const Analyzer::WidthBucketExpr expr,
const CompilationOptions co 
)
private

Definition at line 437 of file IRCodegen.cpp.

References Analyzer::WidthBucketExpr::can_skip_out_of_bound_check(), cgen_state_, CHECK, CHECK_EQ, codegen(), codegenCastBetweenIntTypes(), codegenCmp(), CgenState::context_, CgenState::current_func_, CgenState::emitCall(), Analyzer::WidthBucketExpr::get_lower_bound(), Analyzer::WidthBucketExpr::get_partition_count(), Analyzer::WidthBucketExpr::get_target_value(), Analyzer::WidthBucketExpr::get_upper_bound(), CgenState::inlineFpNull(), CgenState::ir_builder_, kGT, kINT, kONE, CgenState::llInt(), CgenState::needs_error_check_, and toBool().

Referenced by codegen().

438  {
439  auto target_value_expr = expr->get_target_value();
440  auto lower_bound_expr = expr->get_lower_bound();
441  auto upper_bound_expr = expr->get_upper_bound();
442  auto partition_count_expr = expr->get_partition_count();
443 
444  std::string func_name = "width_bucket_expr";
445  bool nullable_expr = false;
446  if (expr->can_skip_out_of_bound_check()) {
447  func_name += "_no_oob_check";
448  } else if (!target_value_expr->get_type_info().get_notnull()) {
449  func_name += "_nullable";
450  nullable_expr = true;
451  }
452 
453  auto target_value_expr_lvs = codegen(target_value_expr, true, co);
454  CHECK_EQ(size_t(1), target_value_expr_lvs.size());
455  auto lower_bound_expr_lvs = codegen(lower_bound_expr, true, co);
456  CHECK_EQ(size_t(1), lower_bound_expr_lvs.size());
457  auto upper_bound_expr_lvs = codegen(upper_bound_expr, true, co);
458  CHECK_EQ(size_t(1), upper_bound_expr_lvs.size());
459  auto partition_count_expr_lvs = codegen(partition_count_expr, true, co);
460  CHECK_EQ(size_t(1), partition_count_expr_lvs.size());
461  auto target_value_ti = target_value_expr->get_type_info();
462  auto null_value_lv = cgen_state_->inlineFpNull(target_value_ti);
463 
464  // check partition count : 1 ~ INT32_MAX
465  // INT32_MAX will be checked during casting by OVERFLOW checking step
466  auto partition_count_ti = partition_count_expr->get_type_info();
467  CHECK(partition_count_ti.is_integer());
468  auto int32_ti = SQLTypeInfo(kINT, partition_count_ti.get_notnull());
469  auto partition_count_expr_lv =
470  codegenCastBetweenIntTypes(partition_count_expr_lvs[0],
471  partition_count_ti,
472  int32_ti,
473  partition_count_ti.get_size() < int32_ti.get_size());
474  llvm::Value* chosen_min = cgen_state_->llInt(static_cast<int32_t>(0));
475  llvm::Value* partition_count_min =
476  cgen_state_->ir_builder_.CreateICmpSLE(partition_count_expr_lv, chosen_min);
477  llvm::BasicBlock* width_bucket_partition_count_ok_bb =
478  llvm::BasicBlock::Create(cgen_state_->context_,
479  "width_bucket_partition_count_ok_bb",
481  llvm::BasicBlock* width_bucket_argument_check_fail_bb =
482  llvm::BasicBlock::Create(cgen_state_->context_,
483  "width_bucket_argument_check_fail_bb",
485  cgen_state_->ir_builder_.CreateCondBr(partition_count_min,
486  width_bucket_argument_check_fail_bb,
487  width_bucket_partition_count_ok_bb);
488  cgen_state_->ir_builder_.SetInsertPoint(width_bucket_argument_check_fail_bb);
489  cgen_state_->ir_builder_.CreateRet(
490  cgen_state_->llInt(int32_t(heavyai::ErrorCode::WIDTH_BUCKET_INVALID_ARGUMENT)));
491  cgen_state_->ir_builder_.SetInsertPoint(width_bucket_partition_count_ok_bb);
492 
493  llvm::BasicBlock* width_bucket_bound_check_ok_bb =
494  llvm::BasicBlock::Create(cgen_state_->context_,
495  "width_bucket_bound_check_ok_bb",
497  llvm::Value* bound_check{nullptr};
498  if (lower_bound_expr->get_type_info().get_notnull() &&
499  upper_bound_expr->get_type_info().get_notnull()) {
500  bound_check = cgen_state_->ir_builder_.CreateFCmpOEQ(
501  lower_bound_expr_lvs[0], upper_bound_expr_lvs[0], "bound_check");
502  } else {
503  std::vector<llvm::Value*> bound_check_args{
504  lower_bound_expr_lvs[0],
505  upper_bound_expr_lvs[0],
506  null_value_lv,
507  cgen_state_->llInt(static_cast<int8_t>(1))};
508  bound_check = toBool(cgen_state_->emitCall("eq_double_nullable", bound_check_args));
509  }
510  cgen_state_->ir_builder_.CreateCondBr(
511  bound_check, width_bucket_argument_check_fail_bb, width_bucket_bound_check_ok_bb);
512  cgen_state_->ir_builder_.SetInsertPoint(width_bucket_bound_check_ok_bb);
514  auto reversed_expr = toBool(codegenCmp(SQLOps::kGT,
515  kONE,
516  lower_bound_expr_lvs,
517  lower_bound_expr->get_type_info(),
518  upper_bound_expr,
519  co));
520  auto lower_bound_expr_lv = lower_bound_expr_lvs[0];
521  auto upper_bound_expr_lv = upper_bound_expr_lvs[0];
522  std::vector<llvm::Value*> width_bucket_args{target_value_expr_lvs[0],
523  reversed_expr,
524  lower_bound_expr_lv,
525  upper_bound_expr_lv,
526  partition_count_expr_lv};
527  if (nullable_expr) {
528  width_bucket_args.push_back(null_value_lv);
529  }
530  return cgen_state_->emitCall(func_name, width_bucket_args);
531 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Expr * get_partition_count() const
Definition: Analyzer.h:1201
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:427
bool needs_error_check_
Definition: CgenState.h:405
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
Definition: sqldefs.h:36
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqldefs.h:74
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:344
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:230
const Expr * get_target_value() const
Definition: Analyzer.h:1198
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
bool can_skip_out_of_bound_check() const
Definition: Analyzer.h:1243
Definition: sqltypes.h:72
const Expr * get_lower_bound() const
Definition: Analyzer.h:1199
const Expr * get_upper_bound() const
Definition: Analyzer.h:1200
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codegenWindowPosition ( const WindowFunctionContext window_func_context,
llvm::Value *  pos_arg 
)

Definition at line 235 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::emitCall(), CgenState::llInt(), and WindowFunctionContext::output().

Referenced by codegenColVar(), Executor::codegenLoadCurrentValueFromColBuf(), and GroupByAndAggregate::codegenWindowRowPointer().

237  {
239  const auto window_position = cgen_state_->emitCall(
240  "row_number_window_func",
241  {cgen_state_->llInt(reinterpret_cast<const int64_t>(window_func_context->output())),
242  pos_arg});
243  return window_position;
244 }
CgenState * cgen_state_
const int8_t * output() const
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::codgenAdjustFixedEncNull ( llvm::Value *  val,
const SQLTypeInfo col_ti 
)
private

Definition at line 448 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_LT, CgenState::context_, CgenState::emitCall(), SQLTypeInfo::get_compression(), SQLTypeInfo::get_dimension(), get_int_type(), SQLTypeInfo::get_logical_size(), anonymous_namespace{ColumnIR.cpp}::get_phys_int_type(), SQLTypeInfo::get_scale(), SQLTypeInfo::get_size(), SQLTypeInfo::get_subtype(), CgenState::inlineIntNull(), CgenState::ir_builder_, kENCODING_DICT, kENCODING_NONE, CgenState::llInt(), numeric_type_name(), and to_string().

Referenced by codegenFixedLengthColVar().

449  {
451  CHECK_LT(col_ti.get_size(), col_ti.get_logical_size());
452  const auto col_phys_width = col_ti.get_size() * 8;
453  auto from_typename = "int" + std::to_string(col_phys_width) + "_t";
454  auto adjusted = cgen_state_->ir_builder_.CreateCast(
455  llvm::Instruction::CastOps::Trunc,
456  val,
457  get_int_type(col_phys_width, cgen_state_->context_));
458  if (col_ti.get_compression() == kENCODING_DICT) {
459  from_typename = "u" + from_typename;
460  llvm::Value* from_null{nullptr};
461  switch (col_ti.get_size()) {
462  case 1:
463  from_null = cgen_state_->llInt(std::numeric_limits<uint8_t>::max());
464  break;
465  case 2:
466  from_null = cgen_state_->llInt(std::numeric_limits<uint16_t>::max());
467  break;
468  default:
469  CHECK(false);
470  }
471  return cgen_state_->emitCall(
472  "cast_" + from_typename + "_to_" + numeric_type_name(col_ti) + "_nullable",
473  {adjusted, from_null, cgen_state_->inlineIntNull(col_ti)});
474  }
475  SQLTypeInfo col_phys_ti(get_phys_int_type(col_ti.get_size()),
476  col_ti.get_dimension(),
477  col_ti.get_scale(),
478  false,
480  0,
481  col_ti.get_subtype());
482  return cgen_state_->emitCall(
483  "cast_" + from_typename + "_to_" + numeric_type_name(col_ti) + "_nullable",
484  {adjusted,
485  cgen_state_->inlineIntNull(col_phys_ti),
486  cgen_state_->inlineIntNull(col_ti)});
487 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:392
HOST DEVICE int get_size() const
Definition: sqltypes.h:403
CgenState * cgen_state_
HOST DEVICE int get_scale() const
Definition: sqltypes.h:396
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string to_string(char const *&&v)
llvm::LLVMContext & context_
Definition: CgenState.h:382
int get_logical_size() const
Definition: sqltypes.h:421
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
#define AUTOMATIC_IR_METADATA(CGENSTATE)
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:217
#define CHECK_LT(x, y)
Definition: Logger.h:303
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:399
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:393
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:230
SQLTypes get_phys_int_type(const size_t byte_sz)
Definition: ColumnIR.cpp:429

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::colByteStream ( const Analyzer::ColumnVar col_var,
const bool  fetch_column,
const bool  hoist_literals 
)
private

Definition at line 574 of file ColumnIR.cpp.

References cgen_state_, CHECK, CHECK_GE, CgenState::context_, PlanState::getLocalColumnId(), plan_state_, CgenState::row_func_, and to_string().

Referenced by codegenColVar().

576  {
577  CHECK_GE(cgen_state_->row_func_->arg_size(), size_t(3));
578  const auto stream_arg_name =
579  "col_buf" + std::to_string(plan_state_->getLocalColumnId(col_var, fetch_column));
580  for (auto& arg : cgen_state_->row_func_->args()) {
581  if (arg.getName() == stream_arg_name) {
582  CHECK(arg.getType() == llvm::Type::getInt8PtrTy(cgen_state_->context_));
583  return &arg;
584  }
585  }
586  CHECK(false);
587  return nullptr;
588 }
CgenState * cgen_state_
#define CHECK_GE(x, y)
Definition: Logger.h:306
std::string to_string(char const *&&v)
llvm::Function * row_func_
Definition: CgenState.h:374
int getLocalColumnId(const Analyzer::ColumnVar *col_var, const bool fetch_column)
Definition: PlanState.cpp:52
llvm::LLVMContext & context_
Definition: CgenState.h:382
PlanState * plan_state_
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::unique_ptr< InValuesBitmap > CodeGenerator::createInValuesBitmap ( const Analyzer::InValues in_values,
const CompilationOptions co 
)
private

Definition at line 112 of file InValuesIR.cpp.

References threading_serial::async(), AUTOMATIC_IR_METADATA, cgen_state_, CHECK, codegenIntConst(), Data_Namespace::CPU_LEVEL, cpu_threads(), CompilationOptions::device_type, executor(), extract_cast_arg(), Analyzer::InValues::get_arg(), get_nullable_type_info(), Analyzer::Expr::get_type_info(), Analyzer::InValues::get_value_list(), GPU, Data_Namespace::GPU_LEVEL, inline_int_null_val(), StringDictionary::INVALID_STR_ID, SQLTypeInfo::is_string(), and kENCODING_DICT.

Referenced by codegen().

114  {
116  const auto& value_list = in_values->get_value_list();
117  const auto val_count = value_list.size();
118  const auto& ti = in_values->get_arg()->get_type_info();
119  if (!(ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT))) {
120  return nullptr;
121  }
122  const auto sdp =
123  ti.is_string()
124  ? executor()->getStringDictionaryProxy(
125  ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true)
126  : nullptr;
127  if (val_count > 3) {
128  using ListIterator = decltype(value_list.begin());
129  std::vector<int64_t> values;
130  const auto needle_null_val = inline_int_null_val(ti);
131  const int worker_count = val_count > 10000 ? cpu_threads() : int(1);
132  std::vector<std::vector<int64_t>> values_set(worker_count, std::vector<int64_t>());
133  std::vector<std::future<bool>> worker_threads;
134  auto start_it = value_list.begin();
135  for (size_t i = 0,
136  start_val = 0,
137  stride = (val_count + worker_count - 1) / worker_count;
138  i < val_count && start_val < val_count;
139  ++i, start_val += stride, std::advance(start_it, stride)) {
140  auto end_it = start_it;
141  std::advance(end_it, std::min(stride, val_count - start_val));
142  const auto do_work = [&](std::vector<int64_t>& out_vals,
143  const ListIterator start,
144  const ListIterator end) -> bool {
145  for (auto val_it = start; val_it != end; ++val_it) {
146  const auto& in_val = *val_it;
147  const auto in_val_const =
148  dynamic_cast<const Analyzer::Constant*>(extract_cast_arg(in_val.get()));
149  if (!in_val_const) {
150  return false;
151  }
152  const auto& in_val_ti = in_val->get_type_info();
153  CHECK(in_val_ti == ti || get_nullable_type_info(in_val_ti) == ti);
154  if (ti.is_string()) {
155  CHECK(sdp);
156  const auto string_id =
157  in_val_const->get_is_null()
158  ? needle_null_val
159  : sdp->getIdOfString(*in_val_const->get_constval().stringval);
160  if (string_id != StringDictionary::INVALID_STR_ID) {
161  out_vals.push_back(string_id);
162  }
163  } else {
164  out_vals.push_back(CodeGenerator::codegenIntConst(in_val_const, cgen_state_)
165  ->getSExtValue());
166  }
167  }
168  return true;
169  };
170  if (worker_count > 1) {
171  worker_threads.push_back(std::async(
172  std::launch::async, do_work, std::ref(values_set[i]), start_it, end_it));
173  } else {
174  do_work(std::ref(values), start_it, end_it);
175  }
176  }
177  bool success = true;
178  for (auto& worker : worker_threads) {
179  success &= worker.get();
180  }
181  if (!success) {
182  return nullptr;
183  }
184  if (worker_count > 1) {
185  size_t total_val_count = 0;
186  for (auto& vals : values_set) {
187  total_val_count += vals.size();
188  }
189  values.reserve(total_val_count);
190  for (auto& vals : values_set) {
191  values.insert(values.end(), vals.begin(), vals.end());
192  }
193  }
194  try {
195  return std::make_unique<InValuesBitmap>(values,
196  needle_null_val,
200  executor()->deviceCount(co.device_type),
201  executor()->data_mgr_,
202  co);
203  } catch (...) {
204  return nullptr;
205  }
206  }
207  return nullptr;
208 }
CgenState * cgen_state_
const Analyzer::Expr * extract_cast_arg(const Analyzer::Expr *expr)
Definition: Execute.h:222
future< Result > async(Fn &&fn, Args &&...args)
static constexpr int32_t INVALID_STR_ID
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
static llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant, CgenState *cgen_state)
Definition: ConstantIR.cpp:89
const std::list< std::shared_ptr< Analyzer::Expr > > & get_value_list() const
Definition: Analyzer.h:646
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool is_string() const
Definition: sqltypes.h:561
int cpu_threads()
Definition: thread_count.h:25
const Expr * get_arg() const
Definition: Analyzer.h:644
SQLTypeInfo get_nullable_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1484
Executor * executor() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createLineStringStructType ( const std::string &  udf_func_name,
size_t  param_num 
)
private

Definition at line 923 of file ExtensionsIR.cpp.

References cgen_state_, CgenState::context_, and CgenState::module_.

Referenced by codegenGeoLineStringArgs().

925  {
926  llvm::Module* module_for_lookup = cgen_state_->module_;
927  llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
928 
929  llvm::StructType* generated_struct_type =
930  llvm::StructType::get(cgen_state_->context_,
931  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
932  llvm::Type::getInt32Ty(cgen_state_->context_),
933  llvm::Type::getInt32Ty(cgen_state_->context_),
934  llvm::Type::getInt32Ty(cgen_state_->context_),
935  llvm::Type::getInt32Ty(cgen_state_->context_)},
936  false);
937 
938  if (udf_func) {
939  llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
940  CHECK(param_num < udf_func_type->getNumParams());
941  llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
942  CHECK(param_pointer_type->isPointerTy());
943  llvm::Type* param_type = param_pointer_type->getPointerElementType();
944  CHECK(param_type->isStructTy());
945  llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
946  CHECK(struct_type->isStructTy());
947  CHECK_EQ(struct_type->getStructNumElements(), 5u);
948 
949  const auto expected_elems = generated_struct_type->elements();
950  const auto current_elems = struct_type->elements();
951  for (size_t i = 0; i < expected_elems.size(); i++) {
952  CHECK_EQ(expected_elems[i], current_elems[i]);
953  }
954  if (struct_type->isLiteral()) {
955  return struct_type;
956  }
957 
958  llvm::StringRef struct_name = struct_type->getStructName();
959 #if LLVM_VERSION_MAJOR >= 12
960  llvm::StructType* line_string_type =
961  struct_type->getTypeByName(cgen_state_->context_, struct_name);
962 #else
963  llvm::StructType* line_string_type = module_for_lookup->getTypeByName(struct_name);
964 #endif
965  CHECK(line_string_type);
966 
967  return line_string_type;
968  }
969  return generated_struct_type;
970 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createMultiLineStringStructType ( const std::string &  udf_func_name,
size_t  param_num 
)
private

Definition at line 1014 of file ExtensionsIR.cpp.

References cgen_state_, CgenState::context_, and CgenState::module_.

Referenced by codegenGeoMultiLineStringArgs().

1016  {
1017  llvm::Module* module_for_lookup = cgen_state_->module_;
1018  llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1019 
1020  llvm::StructType* generated_struct_type =
1021  llvm::StructType::get(cgen_state_->context_,
1022  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
1023  llvm::Type::getInt32Ty(cgen_state_->context_),
1024  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1025  llvm::Type::getInt32Ty(cgen_state_->context_),
1026  llvm::Type::getInt32Ty(cgen_state_->context_),
1027  llvm::Type::getInt32Ty(cgen_state_->context_),
1028  llvm::Type::getInt32Ty(cgen_state_->context_)},
1029  false);
1030 
1031  if (udf_func) {
1032  llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1033  CHECK(param_num < udf_func_type->getNumParams());
1034  llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1035  CHECK(param_pointer_type->isPointerTy());
1036  llvm::Type* param_type = param_pointer_type->getPointerElementType();
1037  CHECK(param_type->isStructTy());
1038  llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1039  CHECK(struct_type->isStructTy());
1040  CHECK_EQ(struct_type->getStructNumElements(), 7u);
1041 
1042  const auto expected_elems = generated_struct_type->elements();
1043  const auto current_elems = struct_type->elements();
1044  for (size_t i = 0; i < expected_elems.size(); i++) {
1045  CHECK_EQ(expected_elems[i], current_elems[i]);
1046  }
1047  if (struct_type->isLiteral()) {
1048  return struct_type;
1049  }
1050 
1051  llvm::StringRef struct_name = struct_type->getStructName();
1052 #if LLVM_VERSION_MAJOR >= 12
1053  llvm::StructType* multi_linestring_type =
1054  struct_type->getTypeByName(cgen_state_->context_, struct_name);
1055 #else
1056  llvm::StructType* multi_linestring_type =
1057  module_for_lookup->getTypeByName(struct_name);
1058 #endif
1059  CHECK(multi_linestring_type);
1060 
1061  return multi_linestring_type;
1062  }
1063  return generated_struct_type;
1064 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createMultiPointStructType ( const std::string &  udf_func_name,
size_t  param_num 
)
private

Definition at line 832 of file ExtensionsIR.cpp.

References cgen_state_, CgenState::context_, and CgenState::module_.

Referenced by codegenGeoMultiPointArgs().

834  {
835  llvm::Module* module_for_lookup = cgen_state_->module_;
836  llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
837 
838  llvm::StructType* generated_struct_type =
839  llvm::StructType::get(cgen_state_->context_,
840  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
841  llvm::Type::getInt32Ty(cgen_state_->context_),
842  llvm::Type::getInt32Ty(cgen_state_->context_),
843  llvm::Type::getInt32Ty(cgen_state_->context_),
844  llvm::Type::getInt32Ty(cgen_state_->context_)},
845  false);
846 
847  if (udf_func) {
848  llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
849  CHECK(param_num < udf_func_type->getNumParams());
850  llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
851  CHECK(param_pointer_type->isPointerTy());
852  llvm::Type* param_type = param_pointer_type->getPointerElementType();
853  CHECK(param_type->isStructTy());
854  llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
855  CHECK(struct_type->isStructTy());
856  CHECK_EQ(struct_type->getStructNumElements(), 5u);
857 
858  const auto expected_elems = generated_struct_type->elements();
859  const auto current_elems = struct_type->elements();
860  for (size_t i = 0; i < expected_elems.size(); i++) {
861  CHECK_EQ(expected_elems[i], current_elems[i]);
862  }
863  if (struct_type->isLiteral()) {
864  return struct_type;
865  }
866 
867  llvm::StringRef struct_name = struct_type->getStructName();
868 #if LLVM_VERSION_MAJOR >= 12
869  llvm::StructType* multi_point_type =
870  struct_type->getTypeByName(cgen_state_->context_, struct_name);
871 #else
872  llvm::StructType* multi_point_type = module_for_lookup->getTypeByName(struct_name);
873 #endif
874  CHECK(multi_point_type);
875 
876  return multi_point_type;
877  }
878  return generated_struct_type;
879 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createMultiPolygonStructType ( const std::string &  udf_func_name,
size_t  param_num 
)
private

Definition at line 1238 of file ExtensionsIR.cpp.

References cgen_state_, CgenState::context_, and CgenState::module_.

Referenced by codegenGeoMultiPolygonArgs().

1240  {
1241  llvm::Function* udf_func = cgen_state_->module_->getFunction(udf_func_name);
1242 
1243  llvm::StructType* generated_struct_type =
1244  llvm::StructType::get(cgen_state_->context_,
1245  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
1246  llvm::Type::getInt32Ty(cgen_state_->context_),
1247  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1248  llvm::Type::getInt32Ty(cgen_state_->context_),
1249  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1250  llvm::Type::getInt32Ty(cgen_state_->context_),
1251  llvm::Type::getInt32Ty(cgen_state_->context_),
1252  llvm::Type::getInt32Ty(cgen_state_->context_),
1253  llvm::Type::getInt32Ty(cgen_state_->context_)},
1254  false);
1255 
1256  if (udf_func) {
1257  llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1258  CHECK(param_num < udf_func_type->getNumParams());
1259  llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1260  CHECK(param_pointer_type->isPointerTy());
1261  llvm::Type* param_type = param_pointer_type->getPointerElementType();
1262  CHECK(param_type->isStructTy());
1263  llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1264  CHECK(struct_type->isStructTy());
1265  CHECK_EQ(struct_type->getStructNumElements(), 9u);
1266  const auto expected_elems = generated_struct_type->elements();
1267  const auto current_elems = struct_type->elements();
1268  for (size_t i = 0; i < expected_elems.size(); i++) {
1269  CHECK_EQ(expected_elems[i], current_elems[i]);
1270  }
1271  if (struct_type->isLiteral()) {
1272  return struct_type;
1273  }
1274  llvm::StringRef struct_name = struct_type->getStructName();
1275 
1276 #if LLVM_VERSION_MAJOR >= 12
1277  llvm::StructType* polygon_type =
1278  struct_type->getTypeByName(cgen_state_->context_, struct_name);
1279 #else
1280  llvm::StructType* polygon_type = cgen_state_->module_->getTypeByName(struct_name);
1281 #endif
1282  CHECK(polygon_type);
1283 
1284  return polygon_type;
1285  }
1286  return generated_struct_type;
1287 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createPointStructType ( const std::string &  udf_func_name,
size_t  param_num 
)
private

Definition at line 744 of file ExtensionsIR.cpp.

References cgen_state_, CgenState::context_, and CgenState::module_.

Referenced by codegenGeoPointArgs().

745  {
746  llvm::Module* module_for_lookup = cgen_state_->module_;
747  llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
748 
749  llvm::StructType* generated_struct_type =
750  llvm::StructType::get(cgen_state_->context_,
751  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
752  llvm::Type::getInt32Ty(cgen_state_->context_),
753  llvm::Type::getInt32Ty(cgen_state_->context_),
754  llvm::Type::getInt32Ty(cgen_state_->context_),
755  llvm::Type::getInt32Ty(cgen_state_->context_)},
756  false);
757 
758  if (udf_func) {
759  llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
760  CHECK(param_num < udf_func_type->getNumParams());
761  llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
762  CHECK(param_pointer_type->isPointerTy());
763  llvm::Type* param_type = param_pointer_type->getPointerElementType();
764  CHECK(param_type->isStructTy());
765  llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
766  CHECK_EQ(struct_type->getStructNumElements(), 5u)
767  << serialize_llvm_object(struct_type);
768  const auto expected_elems = generated_struct_type->elements();
769  const auto current_elems = struct_type->elements();
770  for (size_t i = 0; i < expected_elems.size(); i++) {
771  CHECK_EQ(expected_elems[i], current_elems[i]);
772  }
773  if (struct_type->isLiteral()) {
774  return struct_type;
775  }
776 
777  llvm::StringRef struct_name = struct_type->getStructName();
778 #if LLVM_VERSION_MAJOR >= 12
779  llvm::StructType* point_type =
780  struct_type->getTypeByName(cgen_state_->context_, struct_name);
781 #else
782  llvm::StructType* point_type = module_for_lookup->getTypeByName(struct_name);
783 #endif
784  CHECK(point_type);
785 
786  return point_type;
787  }
788  return generated_struct_type;
789 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
std::string serialize_llvm_object(const T *llvm_obj)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createPolygonStructType ( const std::string &  udf_func_name,
size_t  param_num 
)
private

Definition at line 1130 of file ExtensionsIR.cpp.

References cgen_state_, CgenState::context_, and CgenState::module_.

Referenced by codegenGeoPolygonArgs().

1131  {
1132  llvm::Module* module_for_lookup = cgen_state_->module_;
1133  llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1134 
1135  llvm::StructType* generated_struct_type =
1136  llvm::StructType::get(cgen_state_->context_,
1137  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
1138  llvm::Type::getInt32Ty(cgen_state_->context_),
1139  llvm::Type::getInt8PtrTy(cgen_state_->context_),
1140  llvm::Type::getInt32Ty(cgen_state_->context_),
1141  llvm::Type::getInt32Ty(cgen_state_->context_),
1142  llvm::Type::getInt32Ty(cgen_state_->context_),
1143  llvm::Type::getInt32Ty(cgen_state_->context_)},
1144  false);
1145 
1146  if (udf_func) {
1147  llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1148  CHECK(param_num < udf_func_type->getNumParams());
1149  llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1150  CHECK(param_pointer_type->isPointerTy());
1151  llvm::Type* param_type = param_pointer_type->getPointerElementType();
1152  CHECK(param_type->isStructTy());
1153  llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1154 
1155  CHECK(struct_type->isStructTy());
1156  CHECK_EQ(struct_type->getStructNumElements(), 7u);
1157 
1158  const auto expected_elems = generated_struct_type->elements();
1159  const auto current_elems = struct_type->elements();
1160  for (size_t i = 0; i < expected_elems.size(); i++) {
1161  CHECK_EQ(expected_elems[i], current_elems[i]);
1162  }
1163  if (struct_type->isLiteral()) {
1164  return struct_type;
1165  }
1166 
1167  llvm::StringRef struct_name = struct_type->getStructName();
1168 
1169 #if LLVM_VERSION_MAJOR >= 12
1170  llvm::StructType* polygon_type =
1171  struct_type->getTypeByName(cgen_state_->context_, struct_name);
1172 #else
1173  llvm::StructType* polygon_type = module_for_lookup->getTypeByName(struct_name);
1174 #endif
1175  CHECK(polygon_type);
1176 
1177  return polygon_type;
1178  }
1179  return generated_struct_type;
1180 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::Module * module_
Definition: CgenState.h:373
llvm::LLVMContext & context_
Definition: CgenState.h:382
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

llvm::StructType * CodeGenerator::createStringViewStructType ( )
private

Definition at line 1781 of file ExtensionsIR.cpp.

References cgen_state_, and CgenState::context_.

Referenced by codegen(), codegenCastFromString(), codegenCmp(), codegenStringFetchAndEncode(), and codegenVariableLengthStringColVar().

1781  {
1782  auto* const string_view_type =
1783  llvm::StructType::get(cgen_state_->context_,
1784  {llvm::Type::getInt8PtrTy(cgen_state_->context_),
1785  llvm::Type::getInt64Ty(cgen_state_->context_)});
1786  string_view_type->setName("StringView");
1787  return string_view_type;
1788 }
CgenState * cgen_state_
llvm::LLVMContext & context_
Definition: CgenState.h:382

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::endArgsNullcheck ( const ArgNullcheckBBs bbs,
llvm::Value *  fn_ret_lv,
llvm::Value *  null_array_ptr,
const Analyzer::FunctionOper function_oper 
)
private

Definition at line 461 of file ExtensionsIR.cpp.

References CodeGenerator::ArgNullcheckBBs::args_notnull_bb, CodeGenerator::ArgNullcheckBBs::args_null_bb, AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, anonymous_namespace{ExtensionsIR.cpp}::get_buffer_struct_type(), get_fp_type(), get_int_type(), anonymous_namespace{ExtensionsIR.cpp}::get_llvm_type_from_sql_array_type(), anonymous_namespace{ExtensionsIR.cpp}::get_sql_type_from_llvm_type(), Analyzer::Expr::get_type_info(), Analyzer::FunctionOper::getName(), CgenState::inlineFpNull(), CgenState::inlineIntNull(), CgenState::ir_builder_, and CodeGenerator::ArgNullcheckBBs::orig_bb.

Referenced by codegenFunctionOper(), and codegenFunctionOperWithCustomTypeHandling().

465  {
467  if (bbs.args_null_bb) {
468  CHECK(bbs.args_notnull_bb);
469  cgen_state_->ir_builder_.CreateBr(bbs.args_null_bb);
470  cgen_state_->ir_builder_.SetInsertPoint(bbs.args_null_bb);
471 
472  llvm::PHINode* ext_call_phi{nullptr};
473  llvm::Value* null_lv{nullptr};
474  const auto func_ti = function_oper->get_type_info();
475  if (!func_ti.is_buffer()) {
476  // The pre-cast SQL equivalent of the type returned by the extension function.
477  const auto extension_ret_ti = get_sql_type_from_llvm_type(fn_ret_lv->getType());
478 
479  ext_call_phi = cgen_state_->ir_builder_.CreatePHI(
480  extension_ret_ti.is_fp()
481  ? get_fp_type(extension_ret_ti.get_size() * 8, cgen_state_->context_)
482  : get_int_type(extension_ret_ti.get_size() * 8, cgen_state_->context_),
483  2);
484 
485  null_lv =
486  extension_ret_ti.is_fp()
487  ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(extension_ret_ti))
488  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(extension_ret_ti));
489  } else {
490  const auto arr_struct_ty = get_buffer_struct_type(
491  cgen_state_,
492  function_oper->getName(),
493  0,
495  ext_call_phi =
496  cgen_state_->ir_builder_.CreatePHI(llvm::PointerType::get(arr_struct_ty, 0), 2);
497 
498  CHECK(null_array_ptr);
499  const auto arr_null_bool =
500  cgen_state_->ir_builder_.CreateStructGEP(arr_struct_ty, null_array_ptr, 2);
501  cgen_state_->ir_builder_.CreateStore(
502  llvm::ConstantInt::get(get_int_type(8, cgen_state_->context_), 1),
503  arr_null_bool);
504 
505  const auto arr_null_size =
506  cgen_state_->ir_builder_.CreateStructGEP(arr_struct_ty, null_array_ptr, 1);
507  cgen_state_->ir_builder_.CreateStore(
508  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), 0),
509  arr_null_size);
510  }
511  ext_call_phi->addIncoming(fn_ret_lv, bbs.args_notnull_bb);
512  ext_call_phi->addIncoming(func_ti.is_buffer() ? null_array_ptr : null_lv,
513  bbs.orig_bb);
514 
515  return ext_call_phi;
516  }
517  return fn_ret_lv;
518 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_fp_type(const int width, llvm::LLVMContext &context)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
SQLTypeInfo get_sql_type_from_llvm_type(const llvm::Type *ll_type)
llvm::StructType * get_buffer_struct_type(CgenState *cgen_state, const std::string &ext_func_name, size_t param_num, llvm::Type *elem_type)
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
llvm::Type * get_llvm_type_from_sql_array_type(const SQLTypeInfo ti, llvm::LLVMContext &ctx)
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
#define CHECK(condition)
Definition: Logger.h:291
std::string getName() const
Definition: Analyzer.h:2744
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:104

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Executor* CodeGenerator::executor ( ) const
inlineprotected
llvm::Value * CodeGenerator::foundOuterJoinMatch ( const size_t  nesting_level) const
private

Definition at line 489 of file ColumnIR.cpp.

References cgen_state_, CHECK_GE, CHECK_LE, and CgenState::outer_join_match_found_per_level_.

Referenced by codegenColumn(), and codegenOuterJoinNullPlaceholder().

489  {
490  CHECK_GE(nesting_level, size_t(1));
491  CHECK_LE(nesting_level,
492  static_cast<size_t>(cgen_state_->outer_join_match_found_per_level_.size()));
493  return cgen_state_->outer_join_match_found_per_level_[nesting_level - 1];
494 }
std::vector< llvm::Value * > outer_join_match_found_per_level_
Definition: CgenState.h:395
CgenState * cgen_state_
#define CHECK_GE(x, y)
Definition: Logger.h:306
#define CHECK_LE(x, y)
Definition: Logger.h:304

+ Here is the caller graph for this function:

ExecutionEngineWrapper CodeGenerator::generateNativeCPUCode ( llvm::Function *  func,
const std::unordered_set< llvm::Function * > &  live_funcs,
const CompilationOptions co 
)
static

Definition at line 439 of file NativeCodegen.cpp.

References CHECK, anonymous_namespace{NativeCodegen.cpp}::create_execution_engine(), DEBUG_TIMER, initialize_cpu_backend_mutex_, anonymous_namespace{ExtensionFunctionsGeo.hpp}::None, CompilationOptions::opt_level, anonymous_namespace{NativeCodegen.cpp}::optimize_ir(), and ReductionJIT.

Referenced by TableFunctionCompilationContext::finalize(), ResultSetReductionJIT::finalizeReductionCode(), ScalarCodeGenerator::generateNativeCode(), and StubGenerator::generateStub().

442  {
443  auto timer = DEBUG_TIMER(__func__);
444  llvm::Module* llvm_module = func->getParent();
445  CHECK(llvm_module);
446  // run optimizations
447 #ifndef WITH_JIT_DEBUG
448  llvm::legacy::PassManager pass_manager;
449  optimize_ir(
450  func, llvm_module, pass_manager, live_funcs, /*is_gpu_smem_used=*/false, co);
451 #endif // WITH_JIT_DEBUG
452 
453  // The following lock avoids a data race in two places:
454  // 1) in initializaiton of the CPU backend targets
455  // 1) in llvm::sys::DynamicLibrary::getPermanentLibrary and
456  // GDBJITRegistrationListener::notifyObjectLoaded while creating a
457  // new ExecutionEngine instance in the child call create_execution_engine.
458 
459  // Todo: Initialize backend CPU (and perhaps GPU?) targets at startup
460  // instead of for every compilation, and see if we can reduce
461  // the scope of the below lock
462 
463  std::lock_guard<std::mutex> lock(initialize_cpu_backend_mutex_);
464  auto init_err = llvm::InitializeNativeTarget();
465  CHECK(!init_err);
466 
467  llvm::InitializeAllTargetMCs();
468  llvm::InitializeNativeTargetAsmPrinter();
469  llvm::InitializeNativeTargetAsmParser();
470 
471  std::string err_str;
472  std::unique_ptr<llvm::Module> owner(llvm_module);
473  CHECK(owner);
474  llvm::EngineBuilder eb(std::move(owner));
475  eb.setErrorStr(&err_str);
476  eb.setEngineKind(llvm::EngineKind::JIT);
477  llvm::TargetOptions to;
478  to.EnableFastISel = true;
479  eb.setTargetOptions(to);
481  eb.setOptLevel(llvm::CodeGenOpt::None);
482  }
483 
484  return create_execution_engine(llvm_module, eb, co);
485 }
void optimize_ir(llvm::Function *query_func, llvm::Module *llvm_module, llvm::legacy::PassManager &pass_manager, const std::unordered_set< llvm::Function * > &live_funcs, const bool is_gpu_smem_used, const CompilationOptions &co)
ExecutorOptLevel opt_level
ExecutionEngineWrapper create_execution_engine(llvm::Module *llvm_module, llvm::EngineBuilder &eb, const CompilationOptions &co)
static std::mutex initialize_cpu_backend_mutex_
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< GpuCompilationContext > CodeGenerator::generateNativeGPUCode ( Executor executor,
llvm::Function *  func,
llvm::Function *  wrapper_func,
const std::unordered_set< llvm::Function * > &  live_funcs,
const bool  is_gpu_smem_used,
const CompilationOptions co,
const GPUTarget gpu_target 
)
static

Definition at line 1194 of file NativeCodegen.cpp.

Referenced by TableFunctionCompilationContext::finalize(), and ScalarCodeGenerator::generateNativeGPUCode().

1201  {
1202 #ifdef HAVE_CUDA
1203  auto timer = DEBUG_TIMER(__func__);
1204  auto llvm_module = func->getParent();
1205  /*
1206  `func` is one of the following generated functions:
1207  - `call_table_function(i8** %input_col_buffers, i64*
1208  %input_row_count, i64** %output_buffers, i64* %output_row_count)`
1209  that wraps the user-defined table function.
1210  - `multifrag_query`
1211  - `multifrag_query_hoisted_literals`
1212  - ...
1213 
1214  `wrapper_func` is table_func_kernel(i32*, i8**, i64*, i64**,
1215  i64*) that wraps `call_table_function`.
1216 
1217  `llvm_module` is from `build/QueryEngine/RuntimeFunctions.bc` and it
1218  contains `func` and `wrapper_func`. `llvm_module` should also contain
1219  the definitions of user-defined table functions.
1220 
1221  `live_funcs` contains table_func_kernel and call_table_function
1222 
1223  `gpu_target.cgen_state->module_` appears to be the same as `llvm_module`
1224  */
1225  CHECK(gpu_target.cgen_state->module_ == llvm_module);
1226  CHECK(func->getParent() == wrapper_func->getParent());
1227  llvm_module->setDataLayout(
1228  "e-p:64:64:64-i1:8:8-i8:8:8-"
1229  "i16:16:16-i32:32:32-i64:64:64-"
1230  "f32:32:32-f64:64:64-v16:16:16-"
1231  "v32:32:32-v64:64:64-v128:128:128-n16:32:64");
1232  llvm_module->setTargetTriple("nvptx64-nvidia-cuda");
1233  CHECK(gpu_target.nvptx_target_machine);
1234  llvm::PassManagerBuilder pass_manager_builder = llvm::PassManagerBuilder();
1235 
1236  pass_manager_builder.OptLevel = 0;
1237  llvm::legacy::PassManager module_pass_manager;
1238  pass_manager_builder.populateModulePassManager(module_pass_manager);
1239 
1240  bool requires_libdevice = check_module_requires_libdevice(llvm_module);
1241 
1242  if (requires_libdevice) {
1243  linkModuleWithLibdevice(executor, *llvm_module, pass_manager_builder, gpu_target);
1244  }
1245 
1246  // run optimizations
1247  optimize_ir(func, llvm_module, module_pass_manager, live_funcs, is_gpu_smem_used, co);
1248  legalize_nvvm_ir(func);
1249 
1250  std::stringstream ss;
1251  llvm::raw_os_ostream os(ss);
1252 
1253  llvm::LLVMContext& ctx = llvm_module->getContext();
1254  // Get "nvvm.annotations" metadata node
1255  llvm::NamedMDNode* md = llvm_module->getOrInsertNamedMetadata("nvvm.annotations");
1256 
1257  llvm::Metadata* md_vals[] = {llvm::ConstantAsMetadata::get(wrapper_func),
1258  llvm::MDString::get(ctx, "kernel"),
1259  llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
1260  llvm::Type::getInt32Ty(ctx), 1))};
1261 
1262  // Append metadata to nvvm.annotations
1263  md->addOperand(llvm::MDNode::get(ctx, md_vals));
1264 
1265  std::unordered_set<llvm::Function*> roots{wrapper_func, func};
1266  if (gpu_target.row_func_not_inlined) {
1267  clear_function_attributes(gpu_target.cgen_state->row_func_);
1268  roots.insert(gpu_target.cgen_state->row_func_);
1269  if (gpu_target.cgen_state->filter_func_) {
1270  roots.insert(gpu_target.cgen_state->filter_func_);
1271  }
1272  }
1273 
1274  // prevent helper functions from being removed
1275  for (auto f : gpu_target.cgen_state->helper_functions_) {
1276  roots.insert(f);
1277  }
1278 
1279  if (requires_libdevice) {
1280  for (llvm::Function& F : *llvm_module) {
1281  // Some libdevice functions calls another functions that starts with "__internal_"
1282  // prefix.
1283  // __internal_trig_reduction_slowpathd
1284  // __internal_accurate_pow
1285  // __internal_lgamma_pos
1286  // Those functions have a "noinline" attribute which prevents the optimizer from
1287  // inlining them into the body of @query_func
1288  if (F.hasName() && F.getName().startswith("__internal") && !F.isDeclaration()) {
1289  roots.insert(&F);
1290  }
1291  legalize_nvvm_ir(&F);
1292  }
1293  }
1294 
1295  // Prevent the udf function(s) from being removed the way the runtime functions are
1296  std::unordered_set<std::string> udf_declarations;
1297 
1298  if (executor->has_udf_module(/*is_gpu=*/true)) {
1299  for (auto& f : executor->get_udf_module(/*is_gpu=*/true)->getFunctionList()) {
1300  llvm::Function* udf_function = llvm_module->getFunction(f.getName());
1301 
1302  if (udf_function) {
1303  legalize_nvvm_ir(udf_function);
1304  roots.insert(udf_function);
1305 
1306  // If we have a udf that declares a external function
1307  // note it so we can avoid duplicate declarations
1308  if (f.isDeclaration()) {
1309  udf_declarations.insert(f.getName().str());
1310  }
1311  }
1312  }
1313  }
1314 
1315  if (executor->has_rt_udf_module(/*is_gpu=*/true)) {
1316  for (auto& f : executor->get_rt_udf_module(/*is_gpu=*/true)->getFunctionList()) {
1317  llvm::Function* udf_function = llvm_module->getFunction(f.getName());
1318  if (udf_function) {
1319  legalize_nvvm_ir(udf_function);
1320  roots.insert(udf_function);
1321 
1322  // If we have a udf that declares a external function
1323  // note it so we can avoid duplicate declarations
1324  if (f.isDeclaration()) {
1325  udf_declarations.insert(f.getName().str());
1326  }
1327  }
1328  }
1329  }
1330 
1331  std::vector<llvm::Function*> rt_funcs;
1332  for (auto& Fn : *llvm_module) {
1333  if (roots.count(&Fn)) {
1334  continue;
1335  }
1336  rt_funcs.push_back(&Fn);
1337  }
1338  for (auto& pFn : rt_funcs) {
1339  pFn->removeFromParent();
1340  }
1341 
1342  if (requires_libdevice) {
1343  add_intrinsics_to_module(llvm_module);
1344  }
1345 
1346  if (!llvm_module->getModuleFlag("Debug Info Version")) {
1347  // Fixes QE-705
1348  llvm_module->addModuleFlag(
1349  llvm::Module::Error, "Debug Info Version", llvm::DEBUG_METADATA_VERSION);
1350  }
1351 
1352  llvm_module->print(os, nullptr);
1353  os.flush();
1354 
1355  for (auto& pFn : rt_funcs) {
1356  llvm_module->getFunctionList().push_back(pFn);
1357  }
1358  llvm_module->eraseNamedMetadata(md);
1359 
1360  auto cuda_llir = ss.str() + cuda_rt_decls + extension_function_decls(udf_declarations);
1361  std::string ptx;
1362  try {
1363  ptx = generatePTX(
1364  cuda_llir, gpu_target.nvptx_target_machine, gpu_target.cgen_state->context_);
1365  } catch (ParseIRError& e) {
1366  LOG(WARNING) << "Failed to generate PTX: " << e.what()
1367  << ". Switching to CPU execution target.";
1368  throw QueryMustRunOnCpu();
1369  }
1370  LOG(PTX) << "PTX for the GPU:\n" << ptx << "\nEnd of PTX";
1371 
1372  CubinResult cubin_result = ptx_to_cubin(ptx, gpu_target.cuda_mgr);
1373  auto func_name = wrapper_func->getName().str();
1374  auto gpu_compilation_context = std::make_shared<GpuCompilationContext>();
1375  for (int device_id = 0; device_id < gpu_target.cuda_mgr->getDeviceCount();
1376  ++device_id) {
1377  gpu_compilation_context->addDeviceCode(
1378  std::make_unique<GpuDeviceCompilationContext>(cubin_result.cubin,
1379  cubin_result.cubin_size,
1380  func_name,
1381  device_id,
1382  gpu_target.cuda_mgr,
1383  cubin_result.option_keys.size(),
1384  cubin_result.option_keys.data(),
1385  cubin_result.option_values.data()));
1386  }
1387 
1388  checkCudaErrors(cuLinkDestroy(cubin_result.link_state));
1389  return gpu_compilation_context;
1390 #else
1391  return {};
1392 #endif
1393 }
void optimize_ir(llvm::Function *query_func, llvm::Module *llvm_module, llvm::legacy::PassManager &pass_manager, const std::unordered_set< llvm::Function * > &live_funcs, const bool is_gpu_smem_used, const CompilationOptions &co)
#define LOG(tag)
Definition: Logger.h:285
void checkCudaErrors(CUresult err)
Definition: sample.cpp:38
static std::string generatePTX(const std::string &cuda_llir, llvm::TargetMachine *nvptx_target_machine, llvm::LLVMContext &context)
void * cubin
Definition: NvidiaKernel.h:31
std::vector< CUjit_option > option_keys
Definition: NvidiaKernel.h:32
CubinResult ptx_to_cubin(const std::string &ptx, const CudaMgr_Namespace::CudaMgr *cuda_mgr)
std::vector< void * > option_values
Definition: NvidiaKernel.h:33
void clear_function_attributes(llvm::Function *func)
size_t cubin_size
Definition: NvidiaKernel.h:35
torch::Tensor f(torch::Tensor x, torch::Tensor W_target, torch::Tensor b_target)
static void linkModuleWithLibdevice(Executor *executor, llvm::Module &module, llvm::PassManagerBuilder &pass_manager_builder, const GPUTarget &gpu_target)
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412
CUlinkState link_state
Definition: NvidiaKernel.h:34
Executor * executor() const

+ Here is the caller graph for this function:

std::string CodeGenerator::generatePTX ( const std::string &  cuda_llir,
llvm::TargetMachine *  nvptx_target_machine,
llvm::LLVMContext &  context 
)
static

Definition at line 1478 of file NativeCodegen.cpp.

1480  {
1481  auto timer = DEBUG_TIMER(__func__);
1482  auto mem_buff = llvm::MemoryBuffer::getMemBuffer(cuda_llir, "", false);
1483 
1484  llvm::SMDiagnostic parse_error;
1485 
1486  auto llvm_module = llvm::parseIR(mem_buff->getMemBufferRef(), parse_error, context);
1487  if (!llvm_module) {
1488  LOG(IR) << "CodeGenerator::generatePTX:NVVM IR:\n" << cuda_llir << "\nEnd of NNVM IR";
1489  throw_parseIR_error(parse_error, "generatePTX", /* is_gpu= */ true);
1490  }
1491 
1492  llvm::SmallString<256> code_str;
1493  llvm::raw_svector_ostream formatted_os(code_str);
1494  CHECK(nvptx_target_machine);
1495  {
1496  llvm::legacy::PassManager ptxgen_pm;
1497  llvm_module->setDataLayout(nvptx_target_machine->createDataLayout());
1498 
1499 #if LLVM_VERSION_MAJOR >= 10
1500  nvptx_target_machine->addPassesToEmitFile(
1501  ptxgen_pm, formatted_os, nullptr, llvm::CGFT_AssemblyFile);
1502 #else
1503  nvptx_target_machine->addPassesToEmitFile(
1504  ptxgen_pm, formatted_os, nullptr, llvm::TargetMachine::CGFT_AssemblyFile);
1505 #endif
1506  ptxgen_pm.run(*llvm_module);
1507  }
1508 
1509 #if LLVM_VERSION_MAJOR >= 11
1510  return std::string(code_str);
1511 #else
1512  return code_str.str();
1513 #endif
1514 }
#define LOG(tag)
Definition: Logger.h:285
void throw_parseIR_error(const llvm::SMDiagnostic &parse_error, std::string src="", const bool is_gpu=false)
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412
llvm::Function * CodeGenerator::getArithWithOverflowIntrinsic ( const Analyzer::BinOper bin_oper,
llvm::Type type 
)
private

Definition at line 707 of file ArithmeticIR.cpp.

References cgen_state_, logger::FATAL, Analyzer::BinOper::get_optype(), kMINUS, kMULTIPLY, kPLUS, LOG, CgenState::module_, and Analyzer::BinOper::toString().

Referenced by codegenBinOpWithOverflowForCPU().

709  {
710  llvm::Intrinsic::ID fn_id{llvm::Intrinsic::not_intrinsic};
711  switch (bin_oper->get_optype()) {
712  case kMINUS:
713  fn_id = llvm::Intrinsic::ssub_with_overflow;
714  break;
715  case kPLUS:
716  fn_id = llvm::Intrinsic::sadd_with_overflow;
717  break;
718  case kMULTIPLY:
719  fn_id = llvm::Intrinsic::smul_with_overflow;
720  break;
721  default:
722  LOG(FATAL) << "unexpected arith with overflow optype: " << bin_oper->toString();
723  }
724 
725  return llvm::Intrinsic::getDeclaration(cgen_state_->module_, fn_id, type);
726 }
CgenState * cgen_state_
#define LOG(tag)
Definition: Logger.h:285
Definition: sqldefs.h:43
std::string toString() const override
Definition: Analyzer.cpp:2786
SQLOps get_optype() const
Definition: Analyzer.h:452
llvm::Module * module_
Definition: CgenState.h:373
Definition: sqldefs.h:42

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< const Analyzer::Expr > CodeGenerator::hashJoinLhs ( const Analyzer::ColumnVar rhs) const
private

Definition at line 630 of file ColumnIR.cpp.

References CHECK, Analyzer::Expr::get_type_info(), hashJoinLhsTuple(), SQLTypeInfo::is_array(), is_constructed_point(), IS_EQUIVALENCE, SQLTypeInfo::is_string(), PlanState::join_info_, kCAST, plan_state_, and remove_cast_to_int().

Referenced by codegenColVar().

631  {
632  for (const auto& tautological_eq : plan_state_->join_info_.equi_join_tautologies_) {
633  CHECK(IS_EQUIVALENCE(tautological_eq->get_optype()));
634  if (dynamic_cast<const Analyzer::ExpressionTuple*>(
635  tautological_eq->get_left_operand())) {
636  auto lhs_col = hashJoinLhsTuple(rhs, tautological_eq.get());
637  if (lhs_col) {
638  return lhs_col;
639  }
640  } else {
641  auto eq_right_op = tautological_eq->get_right_operand();
642  if (!rhs->get_type_info().is_string()) {
643  eq_right_op = remove_cast_to_int(eq_right_op);
644  }
645  if (!eq_right_op) {
646  eq_right_op = tautological_eq->get_right_operand();
647  }
648  if (*eq_right_op == *rhs) {
649  auto eq_left_op = tautological_eq->get_left_operand();
650  if (!eq_left_op->get_type_info().is_string()) {
651  eq_left_op = remove_cast_to_int(eq_left_op);
652  }
653  if (!eq_left_op) {
654  eq_left_op = tautological_eq->get_left_operand();
655  }
656  if (eq_left_op->get_type_info().is_geometry()) {
657  // skip cast for a geospatial lhs, since the rhs is likely to be a geospatial
658  // physical col without geospatial type info
659  return nullptr;
660  }
661  if (is_constructed_point(eq_left_op)) {
662  // skip cast for a constructed point lhs
663  return nullptr;
664  }
665  auto eq_left_op_col = dynamic_cast<const Analyzer::ColumnVar*>(eq_left_op);
666  if (!eq_left_op_col) {
667  if (dynamic_cast<const Analyzer::StringOper*>(eq_left_op)) {
668  return nullptr;
669  }
670  if (dynamic_cast<const Analyzer::FunctionOper*>(eq_left_op)) {
671  return nullptr;
672  }
673  auto const cast_expr = dynamic_cast<const Analyzer::UOper*>(eq_left_op);
674  if (cast_expr && cast_expr->get_type_info().is_date()) {
675  // sometimes we add cast operator explicitly when dealing w/ a join between
676  // (encoded) date types. And we have necessary casting logic for hash join
677  // depending on encoding types for date column.
678  // Therefore, we can just pass the column variable it is originated from
679  eq_left_op_col =
680  dynamic_cast<const Analyzer::ColumnVar*>(cast_expr->get_operand());
681  }
682  }
683  CHECK(eq_left_op_col) << "Expect Analyzer::ColumnVar* type expression: "
684  << eq_left_op->toString();
685  if (eq_left_op_col->get_rte_idx() != 0) {
686  return nullptr;
687  }
688  if (rhs->get_type_info().is_string()) {
689  return eq_left_op->deep_copy();
690  }
691  if (rhs->get_type_info().is_array()) {
692  // Note(jclay): Can this be restored from copy as above?
693  // If we fall through to the below return statement,
694  // a superfulous cast from DOUBLE[] to DOUBLE[] is made and
695  // this fails at a later stage in codegen.
696  return nullptr;
697  }
698  return makeExpr<Analyzer::UOper>(
699  rhs->get_type_info(), false, kCAST, eq_left_op->deep_copy());
700  }
701  }
702  }
703  return nullptr;
704 }
JoinInfo join_info_
Definition: PlanState.h:63
const Analyzer::Expr * remove_cast_to_int(const Analyzer::Expr *expr)
Definition: ColumnIR.cpp:618
#define IS_EQUIVALENCE(X)
Definition: sqldefs.h:72
bool is_constructed_point(const Analyzer::Expr *expr)
Definition: Execute.h:1682
Definition: sqldefs.h:51
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
PlanState * plan_state_
#define CHECK(condition)
Definition: Logger.h:291
bool is_string() const
Definition: sqltypes.h:561
std::shared_ptr< const Analyzer::ColumnVar > hashJoinLhsTuple(const Analyzer::ColumnVar *rhs, const Analyzer::BinOper *tautological_eq) const
Definition: ColumnIR.cpp:769
bool is_array() const
Definition: sqltypes.h:585

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< const Analyzer::ColumnVar > CodeGenerator::hashJoinLhsTuple ( const Analyzer::ColumnVar rhs,
const Analyzer::BinOper tautological_eq 
) const
private

Definition at line 769 of file ColumnIR.cpp.

References CHECK, CHECK_EQ, Analyzer::BinOper::get_left_operand(), Analyzer::BinOper::get_right_operand(), and Analyzer::ColumnVar::get_rte_idx().

Referenced by hashJoinLhs(), and needCastForHashJoinLhs().

771  {
772  const auto lhs_tuple_expr =
773  dynamic_cast<const Analyzer::ExpressionTuple*>(tautological_eq->get_left_operand());
774  const auto rhs_tuple_expr = dynamic_cast<const Analyzer::ExpressionTuple*>(
775  tautological_eq->get_right_operand());
776  CHECK(lhs_tuple_expr && rhs_tuple_expr);
777  const auto& lhs_tuple = lhs_tuple_expr->getTuple();
778  const auto& rhs_tuple = rhs_tuple_expr->getTuple();
779  CHECK_EQ(lhs_tuple.size(), rhs_tuple.size());
780  for (size_t i = 0; i < lhs_tuple.size(); ++i) {
781  if (*rhs_tuple[i] == *rhs) {
782  const auto lhs_col =
783  std::static_pointer_cast<const Analyzer::ColumnVar>(lhs_tuple[i]);
784  return lhs_col->get_rte_idx() == 0 ? lhs_col : nullptr;
785  }
786  }
787  return nullptr;
788 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const Expr * get_right_operand() const
Definition: Analyzer.h:456
#define CHECK(condition)
Definition: Logger.h:291
const Expr * get_left_operand() const
Definition: Analyzer.h:455
int32_t get_rte_idx() const
Definition: Analyzer.h:202

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::unique_ptr< llvm::TargetMachine > CodeGenerator::initializeNVPTXBackend ( const CudaMgr_Namespace::NvidiaDeviceArch  arch)
static

Definition at line 1518 of file NativeCodegen.cpp.

Referenced by ScalarCodeGenerator::generateNativeGPUCode().

1519  {
1520  auto timer = DEBUG_TIMER(__func__);
1521 
1522  std::lock_guard<std::mutex> lock(initialize_nvptx_mutex_);
1523 
1524  llvm::InitializeAllTargets();
1525  llvm::InitializeAllTargetMCs();
1526  llvm::InitializeAllAsmPrinters();
1527  std::string err;
1528  auto target = llvm::TargetRegistry::lookupTarget("nvptx64", err);
1529  if (!target) {
1530  LOG(FATAL) << err;
1531  }
1532  return std::unique_ptr<llvm::TargetMachine>(
1533  target->createTargetMachine("nvptx64-nvidia-cuda",
1535  "",
1536  llvm::TargetOptions(),
1537  llvm::Reloc::Static));
1538 }
#define LOG(tag)
Definition: Logger.h:285
static std::string deviceArchToSM(const NvidiaDeviceArch arch)
Definition: CudaMgr.h:162
#define DEBUG_TIMER(name)
Definition: Logger.h:412
static std::mutex initialize_nvptx_mutex_

+ Here is the caller graph for this function:

void CodeGenerator::link_udf_module ( const std::unique_ptr< llvm::Module > &  udf_module,
llvm::Module &  module,
CgenState cgen_state,
llvm::Linker::Flags  flags = llvm::Linker::Flags::None 
)
static

Definition at line 554 of file NativeCodegen.cpp.

References DEBUG_TIMER, logger::ERROR, f(), LOG, anonymous_namespace{ExtensionFunctionsGeo.hpp}::None, VLOG, and CgenState::vmap_.

Referenced by TableFunctionCompilationContext::finalize(), and Executor::optimizeAndCodegenCPU().

557  {
558  auto timer = DEBUG_TIMER(__func__);
559  // throw a runtime error if the target module contains functions
560  // with the same name as in module of UDF functions.
561  for (auto& f : *udf_module) {
562  auto func = llvm_module.getFunction(f.getName());
563  if (!(func == nullptr) && !f.isDeclaration() && flags == llvm::Linker::Flags::None) {
564  LOG(ERROR) << " Attempt to overwrite " << f.getName().str() << " in "
565  << llvm_module.getModuleIdentifier() << " from `"
566  << udf_module->getModuleIdentifier() << "`" << std::endl;
567  throw std::runtime_error(
568  "link_udf_module: *** attempt to overwrite a runtime function with a UDF "
569  "function ***");
570  } else {
571  VLOG(1) << " Adding " << f.getName().str() << " to "
572  << llvm_module.getModuleIdentifier() << " from `"
573  << udf_module->getModuleIdentifier() << "`" << std::endl;
574  }
575  }
576 
577  auto udf_module_copy = llvm::CloneModule(*udf_module, cgen_state->vmap_);
578 
579  udf_module_copy->setDataLayout(llvm_module.getDataLayout());
580  udf_module_copy->setTargetTriple(llvm_module.getTargetTriple());
581 
582  // Initialize linker with module for RuntimeFunctions.bc
583  llvm::Linker ld(llvm_module);
584  bool link_error = false;
585 
586  link_error = ld.linkInModule(std::move(udf_module_copy), flags);
587 
588  if (link_error) {
589  throw std::runtime_error("link_udf_module: *** error linking module ***");
590  }
591 }
#define LOG(tag)
Definition: Logger.h:285
torch::Tensor f(torch::Tensor x, torch::Tensor W_target, torch::Tensor b_target)
#define DEBUG_TIMER(name)
Definition: Logger.h:412
llvm::ValueToValueMapTy vmap_
Definition: CgenState.h:383
#define VLOG(n)
Definition: Logger.h:388

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CodeGenerator::linkModuleWithLibdevice ( Executor executor,
llvm::Module &  module,
llvm::PassManagerBuilder &  pass_manager_builder,
const GPUTarget gpu_target 
)
static

Definition at line 1123 of file NativeCodegen.cpp.

1127  {
1128 #ifdef HAVE_CUDA
1129  auto timer = DEBUG_TIMER(__func__);
1130 
1131  if (!executor->has_libdevice_module()) {
1132  // raise error
1133  throw std::runtime_error(
1134  "libdevice library is not available but required by the UDF module");
1135  }
1136 
1137  // Saves functions \in module
1138  std::vector<llvm::Function*> roots;
1139  for (llvm::Function& fn : llvm_module) {
1140  if (!fn.isDeclaration()) {
1141  roots.emplace_back(&fn);
1142  }
1143  }
1144 
1145  // Bind libdevice to the current module
1146  CodeGenerator::link_udf_module(executor->get_libdevice_module(),
1147  llvm_module,
1148  gpu_target.cgen_state,
1149  llvm::Linker::Flags::OverrideFromSrc);
1150 
1151  std::unordered_set<llvm::Function*> live_funcs =
1152  findAliveRuntimeFuncs(llvm_module, roots);
1153 
1154  std::vector<llvm::Function*> funcs_to_delete;
1155  for (llvm::Function& fn : llvm_module) {
1156  if (!live_funcs.count(&fn)) {
1157  // deleting the function were would invalidate the iterator
1158  funcs_to_delete.emplace_back(&fn);
1159  }
1160  }
1161 
1162  for (llvm::Function* f : funcs_to_delete) {
1163  f->eraseFromParent();
1164  }
1165 
1166  // activate nvvm-reflect-ftz flag on the module
1167 #if LLVM_VERSION_MAJOR >= 11
1168  llvm::LLVMContext& ctx = llvm_module.getContext();
1169  llvm_module.setModuleFlag(llvm::Module::Override,
1170  "nvvm-reflect-ftz",
1171  llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
1172  llvm::Type::getInt32Ty(ctx), uint32_t(1))));
1173 #else
1174  llvm_module.addModuleFlag(llvm::Module::Override, "nvvm-reflect-ftz", uint32_t(1));
1175 #endif
1176  for (llvm::Function& fn : llvm_module) {
1177  fn.addFnAttr("nvptx-f32ftz", "true");
1178  }
1179 
1180  // add nvvm reflect pass replacing any NVVM conditionals with constants
1181  gpu_target.nvptx_target_machine->adjustPassManager(pass_manager_builder);
1182  llvm::legacy::FunctionPassManager FPM(&llvm_module);
1183  pass_manager_builder.populateFunctionPassManager(FPM);
1184 
1185  // Run the NVVMReflectPass here rather than inside optimize_ir
1186  FPM.doInitialization();
1187  for (auto& F : llvm_module) {
1188  FPM.run(F);
1189  }
1190  FPM.doFinalization();
1191 #endif
1192 }
static void link_udf_module(const std::unique_ptr< llvm::Module > &udf_module, llvm::Module &module, CgenState *cgen_state, llvm::Linker::Flags flags=llvm::Linker::Flags::None)
torch::Tensor f(torch::Tensor x, torch::Tensor W_target, torch::Tensor b_target)
#define DEBUG_TIMER(name)
Definition: Logger.h:412
Executor * executor() const
std::unordered_set< llvm::Function * > CodeGenerator::markDeadRuntimeFuncs ( llvm::Module &  module,
const std::vector< llvm::Function * > &  roots,
const std::vector< llvm::Function * > &  leaves 
)
static

Definition at line 1964 of file NativeCodegen.cpp.

1967  {
1968  auto timer = DEBUG_TIMER(__func__);
1969  std::unordered_set<llvm::Function*> live_funcs;
1970  live_funcs.insert(roots.begin(), roots.end());
1971  live_funcs.insert(leaves.begin(), leaves.end());
1972 
1973  if (auto F = llvm_module.getFunction("init_shared_mem_nop")) {
1974  live_funcs.insert(F);
1975  }
1976  if (auto F = llvm_module.getFunction("write_back_nop")) {
1977  live_funcs.insert(F);
1978  }
1979 
1980  for (const llvm::Function* F : roots) {
1981  for (const llvm::BasicBlock& BB : *F) {
1982  for (const llvm::Instruction& I : BB) {
1983  if (const llvm::CallInst* CI = llvm::dyn_cast<const llvm::CallInst>(&I)) {
1984  live_funcs.insert(CI->getCalledFunction());
1985  }
1986  }
1987  }
1988  }
1989 
1990  for (llvm::Function& F : llvm_module) {
1991  if (!live_funcs.count(&F) && !F.isDeclaration()) {
1992  F.setLinkage(llvm::GlobalValue::InternalLinkage);
1993  }
1994  }
1995 
1996  return live_funcs;
1997 }
#define DEBUG_TIMER(name)
Definition: Logger.h:412
bool CodeGenerator::needCastForHashJoinLhs ( const Analyzer::ColumnVar rhs) const
private

Definition at line 706 of file ColumnIR.cpp.

References CHECK, Analyzer::Expr::get_type_info(), hashJoinLhsTuple(), SQLTypeInfo::is_array(), is_constructed_point(), IS_EQUIVALENCE, SQLTypeInfo::is_string(), PlanState::join_info_, plan_state_, and remove_cast_to_int().

Referenced by codegenOuterJoinNullPlaceholder().

706  {
707  for (const auto& tautological_eq : plan_state_->join_info_.equi_join_tautologies_) {
708  CHECK(IS_EQUIVALENCE(tautological_eq->get_optype()));
709  if (dynamic_cast<const Analyzer::ExpressionTuple*>(
710  tautological_eq->get_left_operand())) {
711  auto lhs_col = hashJoinLhsTuple(rhs, tautological_eq.get());
712  if (lhs_col) {
713  // our join column normalizer falls back to the loop join
714  // when columns of two join tables do not have the same types
715  // todo (yoonmin): relax this
716  return false;
717  }
718  } else {
719  auto eq_right_op = tautological_eq->get_right_operand();
720  if (!rhs->get_type_info().is_string()) {
721  eq_right_op = remove_cast_to_int(eq_right_op);
722  }
723  if (!eq_right_op) {
724  eq_right_op = tautological_eq->get_right_operand();
725  }
726  if (*eq_right_op == *rhs) {
727  auto eq_left_op = tautological_eq->get_left_operand();
728  if (!eq_left_op->get_type_info().is_string()) {
729  eq_left_op = remove_cast_to_int(eq_left_op);
730  }
731  if (!eq_left_op) {
732  eq_left_op = tautological_eq->get_left_operand();
733  }
734  if (eq_left_op->get_type_info().is_geometry()) {
735  // skip cast for a geospatial lhs, since the rhs is likely to be a geospatial
736  // physical col without geospatial type info
737  return false;
738  }
739  if (is_constructed_point(eq_left_op)) {
740  // skip cast for a constructed point lhs
741  return false;
742  }
743  auto eq_left_op_col = dynamic_cast<const Analyzer::ColumnVar*>(eq_left_op);
744  if (!eq_left_op_col) {
745  if (dynamic_cast<const Analyzer::StringOper*>(eq_left_op)) {
746  return false;
747  }
748  if (dynamic_cast<const Analyzer::FunctionOper*>(eq_left_op)) {
749  return false;
750  }
751  }
752  CHECK(eq_left_op_col);
753  if (eq_left_op_col->get_rte_idx() != 0) {
754  return false;
755  }
756  if (rhs->get_type_info().is_string()) {
757  return false;
758  }
759  if (rhs->get_type_info().is_array()) {
760  return false;
761  }
762  return true;
763  }
764  }
765  }
766  return false;
767 }
JoinInfo join_info_
Definition: PlanState.h:63
const Analyzer::Expr * remove_cast_to_int(const Analyzer::Expr *expr)
Definition: ColumnIR.cpp:618
#define IS_EQUIVALENCE(X)
Definition: sqldefs.h:72
bool is_constructed_point(const Analyzer::Expr *expr)
Definition: Execute.h:1682
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
PlanState * plan_state_
#define CHECK(condition)
Definition: Logger.h:291
bool is_string() const
Definition: sqltypes.h:561
std::shared_ptr< const Analyzer::ColumnVar > hashJoinLhsTuple(const Analyzer::ColumnVar *rhs, const Analyzer::BinOper *tautological_eq) const
Definition: ColumnIR.cpp:769
bool is_array() const
Definition: sqltypes.h:585

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::posArg ( const Analyzer::Expr expr) const

Definition at line 590 of file ColumnIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CgenState::context_, get_int_type(), CgenState::ir_builder_, run_benchmark_import::result, CgenState::row_func_, and CgenState::scan_idx_to_hash_pos_.

Referenced by GroupByAndAggregate::codegen(), codegen(), GroupByAndAggregate::codegenAggArg(), TargetExprCodegen::codegenAggregate(), codegenArrayAt(), codegenColVar(), codegenFunctionOperCastArgs(), codegenFunctionOperNullArg(), codegenGeoArgs(), codegenGeoOperator(), codegenIsNull(), Executor::codegenJoinLoops(), RangeJoinHashTable::codegenKey(), BoundingBoxIntersectJoinHashTable::codegenKey(), BoundingBoxIntersectJoinHashTable::codegenManyKey(), GroupByAndAggregate::codegenOutputSlot(), codegenQualifierCmp(), codegenRowId(), Executor::codegenWindowFunctionAggregateCalls(), Executor::codegenWindowResetStateControlFlow(), GroupByAndAggregate::codegenWindowRowPointer(), and Executor::groupByColumnCodegen().

590  {
592  const auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(expr);
593  if (col_var && col_var->get_rte_idx() > 0) {
594  const auto hash_pos_it =
595  cgen_state_->scan_idx_to_hash_pos_.find(col_var->get_rte_idx());
596  CHECK(hash_pos_it != cgen_state_->scan_idx_to_hash_pos_.end());
597  if (hash_pos_it->second->getType()->isPointerTy()) {
598  CHECK(hash_pos_it->second->getType()->getPointerElementType()->isIntegerTy(32));
599  llvm::Value* result = cgen_state_->ir_builder_.CreateLoad(
600  hash_pos_it->second->getType()->getPointerElementType(), hash_pos_it->second);
601  result = cgen_state_->ir_builder_.CreateSExt(
602  result, get_int_type(64, cgen_state_->context_));
603  return result;
604  }
605  return hash_pos_it->second;
606  }
607  for (auto& arg : cgen_state_->row_func_->args()) {
608  if (arg.getName() == "pos") {
609  CHECK(arg.getType()->isIntegerTy(64));
610  return &arg;
611  }
612  }
613  abort();
614 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::Function * row_func_
Definition: CgenState.h:374
llvm::LLVMContext & context_
Definition: CgenState.h:382
std::unordered_map< int, llvm::Value * > scan_idx_to_hash_pos_
Definition: CgenState.h:396
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool CodeGenerator::prioritizeQuals ( const RelAlgExecutionUnit ra_exe_unit,
std::vector< Analyzer::Expr * > &  primary_quals,
std::vector< Analyzer::Expr * > &  deferred_quals,
const PlanState::HoistedFiltersSet hoisted_quals 
)
static

Definition at line 158 of file LogicalIR.cpp.

References anonymous_namespace{LogicalIR.cpp}::contains_unsafe_division(), anonymous_namespace{LogicalIR.cpp}::get_likelihood(), RelAlgExecutionUnit::quals, anonymous_namespace{LogicalIR.cpp}::should_defer_eval(), and RelAlgExecutionUnit::simple_quals.

161  {
162  for (auto expr : ra_exe_unit.simple_quals) {
163  if (hoisted_quals.find(expr) != hoisted_quals.end()) {
164  continue;
165  }
166  if (should_defer_eval(expr)) {
167  deferred_quals.push_back(expr.get());
168  continue;
169  }
170  primary_quals.push_back(expr.get());
171  }
172 
173  bool short_circuit = false;
174 
175  for (auto expr : ra_exe_unit.quals) {
176  if (hoisted_quals.find(expr) != hoisted_quals.end()) {
177  continue;
178  }
179 
180  if (get_likelihood(expr.get()) < 0.10 && !contains_unsafe_division(expr.get())) {
181  if (!short_circuit) {
182  primary_quals.push_back(expr.get());
183  short_circuit = true;
184  continue;
185  }
186  }
187  if (short_circuit || should_defer_eval(expr)) {
188  deferred_quals.push_back(expr.get());
189  continue;
190  }
191  primary_quals.push_back(expr.get());
192  }
193 
194  return short_circuit;
195 }
bool should_defer_eval(const std::shared_ptr< Analyzer::Expr > expr)
Definition: LogicalIR.cpp:55
Likelihood get_likelihood(const Analyzer::Expr *expr)
Definition: LogicalIR.cpp:79
std::list< std::shared_ptr< Analyzer::Expr > > quals
bool contains_unsafe_division(const Analyzer::Expr *expr)
Definition: LogicalIR.cpp:26
std::list< std::shared_ptr< Analyzer::Expr > > simple_quals

+ Here is the call graph for this function:

llvm::Value * CodeGenerator::resolveGroupedColumnReference ( const Analyzer::ColumnVar col_var)
private

Definition at line 554 of file ColumnIR.cpp.

References cgen_state_, CHECK, CHECK_GE, CHECK_LE, Analyzer::ColumnVar::get_rte_idx(), Analyzer::ColumnVar::getColumnKey(), CgenState::group_by_expr_cache_, and Analyzer::Var::kGROUPBY.

Referenced by codegenColVar(), and codegenOuterJoinNullPlaceholder().

555  {
556  if (col_var->get_rte_idx() >= 0) {
557  return nullptr;
558  }
559  const auto& column_key = col_var->getColumnKey();
560  CHECK((column_key.column_id == 0) ||
561  (col_var->get_rte_idx() >= 0 && column_key.table_id > 0));
562  const auto var = dynamic_cast<const Analyzer::Var*>(col_var);
563  CHECK(var);
564  const auto var_no = var->get_varno();
565  CHECK_GE(var_no, 1);
566  if (var->get_which_row() == Analyzer::Var::kGROUPBY) {
567  CHECK_LE(static_cast<size_t>(var_no), cgen_state_->group_by_expr_cache_.size());
568  return cgen_state_->group_by_expr_cache_[var_no - 1];
569  }
570  return nullptr;
571 }
CgenState * cgen_state_
#define CHECK_GE(x, y)
Definition: Logger.h:306
std::vector< llvm::Value * > group_by_expr_cache_
Definition: CgenState.h:391
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
#define CHECK_LE(x, y)
Definition: Logger.h:304
#define CHECK(condition)
Definition: Logger.h:291
int32_t get_rte_idx() const
Definition: Analyzer.h:202

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * CodeGenerator::toBool ( llvm::Value *  lv)

Definition at line 344 of file LogicalIR.cpp.

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, and CgenState::ir_builder_.

Referenced by Executor::buildHoistLeftHandSideFiltersCb(), Executor::buildIsDeletedCb(), Executor::buildJoinLoops(), codegen(), codegenCase(), codegenCastBetweenIntTypesOverflowChecks(), codegenDiv(), codegenLogical(), codegenWidthBucketExpr(), and Executor::codegenWindowResetStateControlFlow().

344  {
346  CHECK(lv->getType()->isIntegerTy());
347  if (static_cast<llvm::IntegerType*>(lv->getType())->getBitWidth() > 1) {
348  return cgen_state_->ir_builder_.CreateICmp(
349  llvm::ICmpInst::ICMP_SGT, lv, llvm::ConstantInt::get(lv->getType(), 0));
350  }
351  return lv;
352 }
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define AUTOMATIC_IR_METADATA(CGENSTATE)
#define CHECK(condition)
Definition: Logger.h:291

+ Here is the caller graph for this function:

Friends And Related Function Documentation

friend class GroupByAndAggregate
friend

Definition at line 668 of file CodeGenerator.h.

Member Data Documentation

CgenState* CodeGenerator::cgen_state_
protected

Definition at line 666 of file CodeGenerator.h.

Referenced by beginArgsNullcheck(), Executor::buildJoinLoops(), castArrayPointer(), codegen(), codegenAdd(), GroupByAndAggregate::codegenAggArg(), codegenArith(), codegenArrayAt(), codegenArrayBuff(), codegenArrayExpr(), codegenBinOpWithOverflowForCPU(), codegenBoundingBoxIntersect(), codegenBufferArgs(), codegenCase(), codegenCast(), codegenCastBetweenIntTypes(), codegenCastBetweenIntTypesOverflowChecks(), codegenCastBetweenTimestamps(), codegenCastFromFp(), codegenCastFromString(), codegenCastNonStringToString(), codegenCastTimestampToDate(), codegenCastTimestampToTime(), codegenCastToFp(), codegenCmp(), codegenCmpDecimalConst(), codegenColumn(), ScalarCodeGenerator::codegenColumn(), codegenColVar(), codegenCompression(), codegenConstantWidthBucketExpr(), codegenDateTruncHighPrecisionTimestamps(), codegenDeciDiv(), codegenDictLike(), codegenDictRegexp(), codegenDictStrCmp(), codegenDiv(), codegenExtractHighPrecisionTimestamps(), codegenFixedLengthColVar(), codegenFixedLengthColVarInWindow(), codegenFpArith(), codegenFunctionOper(), codegenFunctionOperCastArgs(), codegenFunctionOperNullArg(), codegenFunctionOperWithCustomTypeHandling(), codegenGeoArgs(), codegenGeoBinOper(), codegenGeoConstant(), codegenGeoLineStringArgs(), codegenGeoMultiLineStringArgs(), codegenGeoMultiPointArgs(), codegenGeoMultiPolygonArgs(), codegenGeoOperator(), codegenGeoPointArgs(), codegenGeoPolygonArgs(), codegenGeosConstructorCall(), codegenGeosPredicateCall(), codegenGeoUOper(), codegenHoistedConstants(), codegenHoistedConstantsLoads(), codegenHoistedConstantsPlaceholders(), codegenIntArith(), codegenIsNull(), codegenIsNullNumber(), codegenLinRegPredict(), codegenLogical(), codegenLogicalShortCircuit(), codegenMod(), codegenMul(), codegenOuterJoinNullPlaceholder(), codegenPerRowStringOper(), codegenPseudoStringOper(), codegenQualifierCmp(), codegenRowId(), codegenSkipOverflowCheckForNull(), codegenStrCmp(), codegenStringFetchAndEncode(), codegenSub(), codegenTreeRegPredict(), codegenUMinus(), codegenUnnest(), codegenVariableLengthStringColVar(), codegenWidthBucketExpr(), codegenWindowPosition(), codgenAdjustFixedEncNull(), colByteStream(), ScalarCodeGenerator::compile(), createInValuesBitmap(), createLineStringStructType(), createMultiLineStringStructType(), createMultiPointStructType(), createMultiPolygonStructType(), createPointStructType(), createPolygonStructType(), createStringViewStructType(), endArgsNullcheck(), foundOuterJoinMatch(), ScalarCodeGenerator::generateNativeGPUCode(), getArithWithOverflowIntrinsic(), posArg(), resolveGroupedColumnReference(), and toBool().

std::mutex CodeGenerator::initialize_cpu_backend_mutex_
staticprivate

Definition at line 675 of file CodeGenerator.h.

Referenced by generateNativeCPUCode().

std::mutex CodeGenerator::initialize_nvptx_mutex_
staticprivate

Definition at line 672 of file CodeGenerator.h.


The documentation for this class was generated from the following files: