OmniSciDB  72c90bc290
 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::string &model_name, const std::shared_ptr< AbstractMLModel > &model, const CompilationOptions &)
 
llvm::Value * codegenTreeRegPredict (const Analyzer::MLPredictExpr *, const std::string &model_name, const std::shared_ptr< AbstractMLModel > &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 28 of file CodeGenerator.h.

Constructor & Destructor Documentation

CodeGenerator::CodeGenerator ( Executor executor)
inline

Definition at line 30 of file CodeGenerator.h.

32  , cgen_state_(executor->cgen_state_.get())
33  , 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 37 of file CodeGenerator.h.

38  : 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 1578 of file NativeCodegen.cpp.

Referenced by CgenState::set_module_shallow_copy().

1578  {
1579  auto const candidate_func_name = func->getName().str();
1582  [candidate_func_name](std::string_view func_name) {
1583  return candidate_func_name == func_name;
1584  });
1585 }
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:2613

+ 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:565
bool is_boolean() const
Definition: sqltypes.h:580
#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:559

+ 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 628 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().

630  {
631  if (uoper->get_type_info().is_decimal()) {
632  return false;
633  }
634 
636  if (executor_) {
637  auto expr_range_info =
638  plan_state_->query_infos_.size() > 0
640  : ExpressionRange::makeInvalidRange();
641  if (expr_range_info.getType() != ExpressionRangeType::Integer) {
642  return false;
643  }
644  if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
645  return true;
646  }
647  }
648 
649  return false;
650 }
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:568
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 187 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_.

189  {
190  if (is_temporary_column(bin_oper->get_left_operand()) ||
191  is_temporary_column(bin_oper->get_right_operand())) {
192  // Computing the range for temporary columns is a lot more expensive than the overflow
193  // check.
194  return false;
195  }
196  if (bin_oper->get_type_info().is_decimal()) {
197  return false;
198  }
199 
201  if (executor_) {
202  auto expr_range_info =
203  plan_state_->query_infos_.size() > 0
205  : ExpressionRange::makeInvalidRange();
206  if (expr_range_info.getType() != ExpressionRangeType::Integer) {
207  return false;
208  }
209  if (expr_range_info.getIntMin() >= min && expr_range_info.getIntMax() <= max) {
210  return true;
211  }
212  }
213 
214  return false;
215 }
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:568
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:261
std::vector< llvm::Value * > codegenGeoExpr(const Analyzer::GeoExpr *, const CompilationOptions &)
Definition: GeoIR.cpp:95
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:181
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:52
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:70
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:75
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:79
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:109
Definition: sqltypes.h:72
double doubleval
Definition: Datum.h:76
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:29
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:71
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:343
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:111
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1694
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  const auto& in_integer_set_ti = in_integer_set->get_type_info();
96  CHECK(in_integer_set_ti.is_boolean());
97  const auto lhs_lvs = codegen(in_arg, true, co);
98  llvm::Value* result{nullptr};
99  if (in_integer_set_ti.get_notnull()) {
100  result = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(cgen_state_->context_),
101  false);
102  } else {
103  result = cgen_state_->llInt(int8_t(0));
104  }
105  CHECK(result);
106  CHECK_EQ(size_t(1), lhs_lvs.size());
107  return cgen_state_->addInValuesBitmap(in_vals_bitmap)
108  ->codegen(lhs_lvs.front(), executor());
109 }
#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:1694
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:48
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:3923
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 295 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.

296  {
297  auto timer = DEBUG_TIMER(__func__);
298  const auto& model_expr = expr->get_model_value();
299  CHECK(model_expr);
300  auto model_constant_expr = dynamic_cast<const Analyzer::Constant*>(model_expr);
301  CHECK(model_constant_expr);
302  const auto model_datum = model_constant_expr->get_constval();
303  const auto model_name_ptr = model_datum.stringval;
304  CHECK(model_name_ptr);
305  const auto model_name = *model_name_ptr;
306  const auto abstract_model = g_ml_models.getModel(model_name);
307  const auto model_type = abstract_model->getModelType();
308  const auto& regressor_exprs = expr->get_regressor_values();
309  if (abstract_model->getNumLogicalFeatures() !=
310  static_cast<int64_t>(regressor_exprs.size())) {
311  std::ostringstream error_oss;
312  error_oss << "ML_PREDICT: Model '" << model_name
313  << "' expects different number of predictor variables ("
314  << abstract_model->getNumLogicalFeatures() << ") than provided ("
315  << regressor_exprs.size() << ").";
316  throw std::runtime_error(error_oss.str());
317  }
318 
319  switch (model_type) {
321  return codegenLinRegPredict(expr, model_name, abstract_model, co);
322  }
326  return codegenTreeRegPredict(expr, model_name, abstract_model, co);
327  }
328  default: {
329  throw std::runtime_error("Unsupported model type.");
330  }
331  }
332 }
llvm::Value * codegenLinRegPredict(const Analyzer::MLPredictExpr *, const std::string &model_name, const std::shared_ptr< AbstractMLModel > &model, const CompilationOptions &)
std::shared_ptr< AbstractMLModel > getModel(const std::string &model_name) const
Definition: MLModel.h:50
MLModelMap g_ml_models
Definition: MLModel.h:124
llvm::Value * codegenTreeRegPredict(const Analyzer::MLPredictExpr *, const std::string &model_name, const std::shared_ptr< AbstractMLModel > &model, const CompilationOptions &)
#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:40
int32_t intval
Definition: Datum.h:73
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:50
MLModelMap g_ml_models
Definition: MLModel.h:124
Definition: sqldefs.h:39
Definition: sqldefs.h:71
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:69
double doubleval
Definition: Datum.h:76
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{
635  str_lv[1], str_lv[2], like_expr_arg_lvs[1], like_expr_arg_lvs[2]};
636  std::string fn_name{expr->get_is_ilike() ? "string_ilike" : "string_like"};
637  if (expr->get_is_simple()) {
638  fn_name += "_simple";
639  } else {
640  str_like_args.push_back(cgen_state_->llInt(int8_t(escape_char)));
641  }
642  if (is_nullable) {
643  fn_name += "_nullable";
644  str_like_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
645  }
646  return cgen_state_->emitCall(fn_name, str_like_args);
647 }
#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:1694
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 842 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().

843  {
845  if (is_unnest(extract_cast_arg(expr->get_arg()))) {
846  throw std::runtime_error("REGEXP not supported for unnested expressions");
847  }
848  char escape_char{'\\'};
849  if (expr->get_escape_expr()) {
850  auto escape_char_expr =
851  dynamic_cast<const Analyzer::Constant*>(expr->get_escape_expr());
852  CHECK(escape_char_expr);
853  CHECK(escape_char_expr->get_type_info().is_string());
854  CHECK_EQ(size_t(1), escape_char_expr->get_constval().stringval->size());
855  escape_char = (*escape_char_expr->get_constval().stringval)[0];
856  }
857  auto pattern = dynamic_cast<const Analyzer::Constant*>(expr->get_pattern_expr());
858  CHECK(pattern);
859  auto fast_dict_pattern_lv =
860  codegenDictRegexp(expr->get_own_arg(), pattern, escape_char, co);
861  if (fast_dict_pattern_lv) {
862  return fast_dict_pattern_lv;
863  }
864  const auto& ti = expr->get_arg()->get_type_info();
865  CHECK(ti.is_string());
866  if (g_enable_watchdog && ti.get_compression() != kENCODING_NONE) {
867  throw WatchdogException(
868  "Cannot do REGEXP_LIKE on this dictionary encoded column, its cardinality is too "
869  "high");
870  }
871  // Now we know we are working on NONE ENCODED column. So switch back to CPU
873  throw QueryMustRunOnCpu();
874  }
875  auto str_lv = codegen(expr->get_arg(), true, co);
876  if (str_lv.size() != 3) {
877  CHECK_EQ(size_t(1), str_lv.size());
878  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 0));
879  str_lv.push_back(cgen_state_->ir_builder_.CreateExtractValue(str_lv.front(), 1));
880  str_lv.back() = cgen_state_->ir_builder_.CreateTrunc(
881  str_lv.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
882  }
883  auto regexp_expr_arg_lvs = codegen(expr->get_pattern_expr(), true, co);
884  CHECK_EQ(size_t(3), regexp_expr_arg_lvs.size());
885  const bool is_nullable{!expr->get_arg()->get_type_info().get_notnull()};
886  std::vector<llvm::Value*> regexp_args{
887  str_lv[1], str_lv[2], regexp_expr_arg_lvs[1], regexp_expr_arg_lvs[2]};
888  std::string fn_name("regexp_like");
889  regexp_args.push_back(cgen_state_->llInt(int8_t(escape_char)));
890  if (is_nullable) {
891  fn_name += "_nullable";
892  regexp_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
894  fn_name, get_int_type(8, cgen_state_->context_), regexp_args);
895  }
897  fn_name, get_int_type(1, cgen_state_->context_), regexp_args);
898 }
#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:1694
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:61
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:62
llvm::Value * codegenCmp(const Analyzer::BinOper *, const CompilationOptions &)
Definition: CompareIR.cpp:230
llvm::Value * codegenLogical(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:298
#define IS_COMPARISON(X)
Definition: sqldefs.h:58

+ 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:48
llvm::Value * codegenIsNull(const Analyzer::UOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:380
#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:298
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
Definition: sqldefs.h:38
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 217 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(), Executor::ERR_OVERFLOW_OR_UNDERFLOW, 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().

223  {
225  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
226  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
227  llvm::Value* chosen_max{nullptr};
228  llvm::Value* chosen_min{nullptr};
229  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
230  auto need_overflow_check =
231  !checkExpressionRanges(bin_oper,
232  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
233  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
234 
235  if (need_overflow_check && co.device_type == ExecutorDeviceType::CPU) {
237  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
238  }
239 
240  llvm::BasicBlock* add_ok{nullptr};
241  llvm::BasicBlock* add_fail{nullptr};
242  if (need_overflow_check) {
244  add_ok = llvm::BasicBlock::Create(
246  if (!null_check_suffix.empty()) {
247  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, add_ok, ti);
248  }
249  add_fail = llvm::BasicBlock::Create(
251  llvm::Value* detected{nullptr};
252  auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0, true);
253  auto overflow = cgen_state_->ir_builder_.CreateAnd(
254  cgen_state_->ir_builder_.CreateICmpSGT(lhs_lv, const_zero),
255  cgen_state_->ir_builder_.CreateICmpSGT(
256  rhs_lv, cgen_state_->ir_builder_.CreateSub(chosen_max, lhs_lv)));
257  auto underflow = cgen_state_->ir_builder_.CreateAnd(
258  cgen_state_->ir_builder_.CreateICmpSLT(lhs_lv, const_zero),
259  cgen_state_->ir_builder_.CreateICmpSLT(
260  rhs_lv, cgen_state_->ir_builder_.CreateSub(chosen_min, lhs_lv)));
261  detected = cgen_state_->ir_builder_.CreateOr(overflow, underflow);
262  cgen_state_->ir_builder_.CreateCondBr(detected, add_fail, add_ok);
263  cgen_state_->ir_builder_.SetInsertPoint(add_ok);
264  }
265  auto ret = null_check_suffix.empty()
266  ? cgen_state_->ir_builder_.CreateAdd(lhs_lv, rhs_lv)
268  "add_" + null_typename + null_check_suffix,
269  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
270  if (need_overflow_check) {
271  cgen_state_->ir_builder_.SetInsertPoint(add_fail);
272  cgen_state_->ir_builder_.CreateRet(
274  cgen_state_->ir_builder_.SetInsertPoint(add_ok);
275  }
276  return ret;
277 }
#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:565
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)
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
bool is_timeinterval() const
Definition: sqltypes.h:592
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:568
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 36 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().

37  {
39  const auto optype = bin_oper->get_optype();
40  CHECK(IS_ARITHMETIC(optype));
41  const auto lhs = bin_oper->get_left_operand();
42  const auto rhs = bin_oper->get_right_operand();
43  const auto& lhs_type = lhs->get_type_info();
44  const auto& rhs_type = rhs->get_type_info();
45 
46  if (lhs_type.is_decimal() && rhs_type.is_decimal() && optype == kDIVIDE) {
47  const auto ret = codegenDeciDiv(bin_oper, co);
48  if (ret) {
49  return ret;
50  }
51  }
52 
53  auto lhs_lv = codegen(lhs, true, co).front();
54  auto rhs_lv = codegen(rhs, true, co).front();
55  // Handle operations when a time interval operand is involved, an operation
56  // between an integer and a time interval isn't normalized by the analyzer.
57  if (lhs_type.is_timeinterval()) {
58  rhs_lv = codegenCastBetweenIntTypes(rhs_lv, rhs_type, lhs_type);
59  } else if (rhs_type.is_timeinterval()) {
60  lhs_lv = codegenCastBetweenIntTypes(lhs_lv, lhs_type, rhs_type);
61  } else {
62  CHECK_EQ(lhs_type.get_type(), rhs_type.get_type());
63  }
64  if (lhs_type.is_integer() || lhs_type.is_decimal() || lhs_type.is_timeinterval()) {
65  return codegenIntArith(bin_oper, lhs_lv, rhs_lv, co);
66  }
67  if (lhs_type.is_fp()) {
68  return codegenFpArith(bin_oper, lhs_lv, rhs_lv);
69  }
70  CHECK(false);
71  return nullptr;
72 }
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:62
#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:975

+ 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:2894
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:2892
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:2893
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:2896
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 726 of file ArithmeticIR.cpp.

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

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

731  {
734 
735  llvm::BasicBlock* check_ok = llvm::BasicBlock::Create(
737  llvm::BasicBlock* check_fail = llvm::BasicBlock::Create(
738  cgen_state_->context_, "ovf_detected", cgen_state_->current_func_);
739  llvm::BasicBlock* null_check{nullptr};
740 
741  if (!null_check_suffix.empty()) {
742  null_check = cgen_state_->ir_builder_.GetInsertBlock();
743  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, check_ok, ti);
744  }
745 
746  // Compute result and overflow flag
747  auto func = getArithWithOverflowIntrinsic(bin_oper, lhs_lv->getType());
748  auto ret_and_overflow = cgen_state_->ir_builder_.CreateCall(
749  func, std::vector<llvm::Value*>{lhs_lv, rhs_lv});
750  auto ret = cgen_state_->ir_builder_.CreateExtractValue(ret_and_overflow,
751  std::vector<unsigned>{0});
752  auto overflow = cgen_state_->ir_builder_.CreateExtractValue(ret_and_overflow,
753  std::vector<unsigned>{1});
754  auto val_bb = cgen_state_->ir_builder_.GetInsertBlock();
755 
756  // Return error on overflow
757  cgen_state_->ir_builder_.CreateCondBr(overflow, check_fail, check_ok);
758  cgen_state_->ir_builder_.SetInsertPoint(check_fail);
759  cgen_state_->ir_builder_.CreateRet(
761 
762  cgen_state_->ir_builder_.SetInsertPoint(check_ok);
763 
764  // In case of null check we have to use NULL result on check fail
765  if (null_check) {
766  auto phi = cgen_state_->ir_builder_.CreatePHI(ret->getType(), 2);
767  phi->addIncoming(llvm::ConstantInt::get(ret->getType(), inline_int_null_val(ti)),
768  null_check);
769  phi->addIncoming(ret, val_bb);
770  ret = phi;
771  }
772 
773  return ret;
774 }
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)
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
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:73
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:105
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqltypes.h:72
Definition: Datum.h:69
#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:343
#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:48
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:1044
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:577
llvm::LLVMContext & context_
Definition: CgenState.h:382
bool is_integer() const
Definition: sqltypes.h:565
bool is_text_encoding_dict() const
Definition: sqltypes.h:615
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:580
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:559
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:568

+ 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:419
bool is_integer() const
Definition: sqltypes.h:565
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:568

+ 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(
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:419
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
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:343
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:571
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:574
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:382
bool is_integer() const
Definition: sqltypes.h:565
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:482
#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:568
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:658
#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:482
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:559
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:1055
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
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
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)
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:559
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
const shared::StringDictKey & getStringDictKey() const
Definition: sqltypes.h:1055
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:275
CgenState * cgen_state_
bool is_fp() const
Definition: sqltypes.h:571
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:482
#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:69
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:404
#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:31
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:30
llvm::Value * codegenLogical(const Analyzer::BinOper *, const CompilationOptions &)
Definition: LogicalIR.cpp:298
const Expr * get_left_operand() const
Definition: Analyzer.h:455
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1694
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 457 of file CompareIR.cpp.

References AUTOMATIC_IR_METADATA, CgenState::castToTypeIn(), cgen_state_, CHECK, CHECK_EQ, codegen(), codegenQualifierCmp(), CgenState::context_, CgenState::emitCall(), 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(), SQLTypeInfo::is_geometry(), SQLTypeInfo::is_integer(), SQLTypeInfo::is_string(), SQLTypeInfo::is_time(), SQLTypeInfo::is_timeinterval(), kBBOX_INTERSECT, kBOOLEAN, kDOUBLE, kENCODING_NONE, kEQ, 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(), and anonymous_namespace{CompareIR.cpp}::string_cmp_func().

462  {
464  CHECK(IS_COMPARISON(optype));
465  const auto& rhs_ti = rhs->get_type_info();
466  if (rhs_ti.is_array()) {
467  return codegenQualifierCmp(optype, qualifier, lhs_lvs, rhs, co);
468  }
469  auto rhs_lvs = codegen(rhs, true, co);
470  CHECK_EQ(kONE, qualifier);
471  if (optype == kBBOX_INTERSECT) {
472  CHECK(lhs_ti.is_geometry());
473  CHECK(rhs_ti.is_array() ||
474  rhs_ti.is_geometry()); // allow geo col or bounds col to pass
475  } else {
476  CHECK((lhs_ti.get_type() == rhs_ti.get_type()) ||
477  (lhs_ti.is_string() && rhs_ti.is_string()));
478  }
479  const auto null_check_suffix = get_null_check_suffix(lhs_ti, rhs_ti);
480  if (lhs_ti.is_integer() || lhs_ti.is_decimal() || lhs_ti.is_time() ||
481  lhs_ti.is_boolean() || lhs_ti.is_string() || lhs_ti.is_timeinterval()) {
482  if (lhs_ti.is_string()) {
483  CHECK(rhs_ti.is_string());
484  CHECK_EQ(lhs_ti.get_compression(), rhs_ti.get_compression());
485  if (lhs_ti.get_compression() == kENCODING_NONE) {
486  // unpack pointer + length if necessary
487  if (lhs_lvs.size() != 3) {
488  CHECK_EQ(size_t(1), lhs_lvs.size());
489  lhs_lvs.push_back(cgen_state_->ir_builder_.CreateExtractValue(lhs_lvs[0], 0));
490  lhs_lvs.push_back(cgen_state_->ir_builder_.CreateExtractValue(lhs_lvs[0], 1));
491  lhs_lvs.back() = cgen_state_->ir_builder_.CreateTrunc(
492  lhs_lvs.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
493  }
494  if (rhs_lvs.size() != 3) {
495  CHECK_EQ(size_t(1), rhs_lvs.size());
496  rhs_lvs.push_back(cgen_state_->ir_builder_.CreateExtractValue(rhs_lvs[0], 0));
497  rhs_lvs.push_back(cgen_state_->ir_builder_.CreateExtractValue(rhs_lvs[0], 1));
498  rhs_lvs.back() = cgen_state_->ir_builder_.CreateTrunc(
499  rhs_lvs.back(), llvm::Type::getInt32Ty(cgen_state_->context_));
500  }
501  std::vector<llvm::Value*> str_cmp_args{
502  lhs_lvs[1], lhs_lvs[2], rhs_lvs[1], rhs_lvs[2]};
503  if (!null_check_suffix.empty()) {
504  str_cmp_args.push_back(
506  }
507  return cgen_state_->emitCall(
508  string_cmp_func(optype) + (null_check_suffix.empty() ? "" : "_nullable"),
509  str_cmp_args);
510  } else {
511  CHECK(optype == kEQ || optype == kNE);
512  }
513  }
514 
515  if (lhs_ti.is_boolean() && rhs_ti.is_boolean()) {
516  auto& lhs_lv = lhs_lvs.front();
517  auto& rhs_lv = rhs_lvs.front();
518  CHECK(lhs_lv->getType()->isIntegerTy());
519  CHECK(rhs_lv->getType()->isIntegerTy());
520  if (lhs_lv->getType()->getIntegerBitWidth() <
521  rhs_lv->getType()->getIntegerBitWidth()) {
522  lhs_lv =
523  cgen_state_->castToTypeIn(lhs_lv, rhs_lv->getType()->getIntegerBitWidth());
524  } else {
525  rhs_lv =
526  cgen_state_->castToTypeIn(rhs_lv, lhs_lv->getType()->getIntegerBitWidth());
527  }
528  }
529 
530  return null_check_suffix.empty()
531  ? cgen_state_->ir_builder_.CreateICmp(
532  llvm_icmp_pred(optype), lhs_lvs.front(), rhs_lvs.front())
534  icmp_name(optype) + "_" + numeric_type_name(lhs_ti) +
535  null_check_suffix,
536  {lhs_lvs.front(),
537  rhs_lvs.front(),
540  }
541  if (lhs_ti.get_type() == kFLOAT || lhs_ti.get_type() == kDOUBLE) {
542  return null_check_suffix.empty()
543  ? cgen_state_->ir_builder_.CreateFCmp(
544  llvm_fcmp_pred(optype), lhs_lvs.front(), rhs_lvs.front())
546  icmp_name(optype) + "_" + numeric_type_name(lhs_ti) +
547  null_check_suffix,
548  {lhs_lvs.front(),
549  rhs_lvs.front(),
550  lhs_ti.get_type() == kFLOAT ? cgen_state_->llFp(NULL_FLOAT)
553  }
554  CHECK(false);
555  return nullptr;
556 }
#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
CgenState * cgen_state_
#define NULL_FLOAT
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:29
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:577
llvm::LLVMContext & context_
Definition: CgenState.h:382
bool is_integer() const
Definition: sqltypes.h:565
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool is_timeinterval() const
Definition: sqltypes.h:592
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
bool is_boolean() const
Definition: sqltypes.h:580
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string get_null_check_suffix(const SQLTypeInfo &lhs_ti, const SQLTypeInfo &rhs_ti)
Definition: Execute.h:1678
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:71
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:558
Definition: sqldefs.h:31
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:595
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:559
bool is_decimal() const
Definition: sqltypes.h:568
std::string string_cmp_func(const SQLOps optype)
Definition: CompareIR.cpp:106
#define IS_COMPARISON(X)
Definition: sqldefs.h:58

+ 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 404 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().

409  {
411  auto u_oper = dynamic_cast<const Analyzer::UOper*>(lhs);
412  if (!u_oper || u_oper->get_optype() != kCAST) {
413  return nullptr;
414  }
415  auto rhs_constant = dynamic_cast<const Analyzer::Constant*>(rhs);
416  if (!rhs_constant) {
417  return nullptr;
418  }
419  const auto operand = u_oper->get_operand();
420  const auto& operand_ti = operand->get_type_info();
421  if (operand_ti.is_decimal() && operand_ti.get_scale() < lhs_ti.get_scale()) {
422  // lhs decimal type has smaller scale
423  } else if (operand_ti.is_integer() && 0 < lhs_ti.get_scale()) {
424  // lhs is integer, no need to scale it all the way up to the cmp expr scale
425  } else {
426  return nullptr;
427  }
428 
429  auto scale_diff = lhs_ti.get_scale() - operand_ti.get_scale() - 1;
430  int64_t bigintval = rhs_constant->get_constval().bigintval;
431  bool negative = false;
432  if (bigintval < 0) {
433  negative = true;
434  bigintval = -bigintval;
435  }
436  int64_t truncated_decimal = bigintval / exp_to_scale(scale_diff);
437  int64_t decimal_tail = bigintval % exp_to_scale(scale_diff);
438  if (truncated_decimal % 10 == 0 && decimal_tail > 0) {
439  truncated_decimal += 1;
440  }
443  lhs_ti.get_scale() - scale_diff,
444  operand_ti.get_notnull());
445  if (negative) {
446  truncated_decimal = -truncated_decimal;
447  }
448  Datum d;
449  d.bigintval = truncated_decimal;
450  const auto new_rhs_lit =
451  makeExpr<Analyzer::Constant>(new_ti, rhs_constant->get_is_null(), d);
452  const auto operand_lv = codegen(operand, true, co).front();
453  const auto lhs_lv = codegenCast(operand_lv, operand_ti, new_ti, false, co);
454  return codegenCmp(optype, qualifier, {lhs_lv}, new_ti, new_rhs_lit.get(), co);
455 }
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:48
int64_t bigintval
Definition: Datum.h:74
#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:69

+ 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:3525
#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:3913
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:3923
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:69
double doubleval
Definition: Datum.h:76

+ 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:1034
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 544 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().

545  {
547  auto lhs = bin_oper->get_left_operand();
548  auto rhs = bin_oper->get_right_operand();
549  const auto& lhs_type = lhs->get_type_info();
550  const auto& rhs_type = rhs->get_type_info();
551  CHECK(lhs_type.is_decimal() && rhs_type.is_decimal() &&
552  lhs_type.get_scale() == rhs_type.get_scale());
553 
554  auto rhs_constant = dynamic_cast<const Analyzer::Constant*>(rhs);
555  auto rhs_cast = dynamic_cast<const Analyzer::UOper*>(rhs);
556  if (rhs_constant && !rhs_constant->get_is_null() &&
557  rhs_constant->get_constval().bigintval != 0LL &&
558  (rhs_constant->get_constval().bigintval % exp_to_scale(rhs_type.get_scale())) ==
559  0LL) {
560  // can safely downscale a scaled constant
561  } else if (rhs_cast && rhs_cast->get_optype() == kCAST &&
562  rhs_cast->get_operand()->get_type_info().is_integer()) {
563  // can skip upscale in the int to dec cast
564  } else {
565  return nullptr;
566  }
567 
568  auto lhs_lv = codegen(lhs, true, co).front();
569  llvm::Value* rhs_lv{nullptr};
570  if (rhs_constant) {
571  const auto rhs_lit = Parser::IntLiteral::analyzeValue(
572  rhs_constant->get_constval().bigintval / exp_to_scale(rhs_type.get_scale()));
573  auto rhs_lit_lv = CodeGenerator::codegenIntConst(
574  dynamic_cast<const Analyzer::Constant*>(rhs_lit.get()), cgen_state_);
576  rhs_lit_lv, rhs_lit->get_type_info(), lhs_type, /*upscale*/ false);
577  } else if (rhs_cast) {
578  auto rhs_cast_oper = rhs_cast->get_operand();
579  const auto& rhs_cast_oper_ti = rhs_cast_oper->get_type_info();
580  auto rhs_cast_oper_lv = codegen(rhs_cast_oper, true, co).front();
582  rhs_cast_oper_lv, rhs_cast_oper_ti, lhs_type, /*upscale*/ false);
583  } else {
584  CHECK(false);
585  }
586  const auto int_typename = numeric_or_time_interval_type_name(lhs_type, rhs_type);
587  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
588  return codegenDiv(lhs_lv,
589  rhs_lv,
590  null_check_suffix.empty() ? "" : int_typename,
591  null_check_suffix,
592  lhs_type,
593  /*upscale*/ false);
594 }
CgenState * cgen_state_
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:165
const Expr * get_right_operand() const
Definition: Analyzer.h:456
Definition: sqldefs.h:48
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:1678
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 670 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().

676  {
678  const auto cast_oper = std::dynamic_pointer_cast<Analyzer::UOper>(like_arg);
679  if (!cast_oper) {
680  return nullptr;
681  }
682  CHECK(cast_oper);
683  CHECK_EQ(kCAST, cast_oper->get_optype());
684  const auto dict_like_arg = cast_oper->get_own_operand();
685  const auto& dict_like_arg_ti = dict_like_arg->get_type_info();
686  if (!dict_like_arg_ti.is_string()) {
687  throw(std::runtime_error("Cast from " + dict_like_arg_ti.get_type_name() + " to " +
688  cast_oper->get_type_info().get_type_name() +
689  " not supported"));
690  }
691  CHECK_EQ(kENCODING_DICT, dict_like_arg_ti.get_compression());
692  const auto sdp = executor()->getStringDictionaryProxy(
693  dict_like_arg_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true);
694  if (sdp->storageEntryCount() > 200000000) {
695  return nullptr;
696  }
697  if (sdp->getDictKey().isTransientDict()) {
698  // If we have a literal dictionary it was a product
699  // of string ops applied to none-encoded strings, and
700  // will not be populated at codegen-time, so we
701  // cannot use the fast path
702 
703  // Todo(todd): Once string ops support non-string producting
704  // operators (like like/ilike), like/ilike can be chained and
705  // we can avoid the string translation
706  return nullptr;
707  }
708  const auto string_oper = dynamic_cast<const Analyzer::StringOper*>(dict_like_arg.get());
709  if (string_oper) {
710  pre_translate_string_ops(string_oper, executor());
711  }
712  const auto& pattern_ti = pattern->get_type_info();
713  CHECK(pattern_ti.is_string());
714  CHECK_EQ(kENCODING_NONE, pattern_ti.get_compression());
715  const auto& pattern_datum = pattern->get_constval();
716  const auto& pattern_str = *pattern_datum.stringval;
717  const auto matching_ids = sdp->getLike(pattern_str, ilike, is_simple, escape_char);
718  // InIntegerSet requires 64-bit values
719  std::vector<int64_t> matching_ids_64(matching_ids.size());
720  std::copy(matching_ids.begin(), matching_ids.end(), matching_ids_64.begin());
721  const auto in_values = std::make_shared<Analyzer::InIntegerSet>(
722  dict_like_arg, matching_ids_64, dict_like_arg_ti.get_notnull());
723  return codegen(in_values.get(), co);
724 }
#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:48
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: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
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::codegenDictRegexp ( const std::shared_ptr< Analyzer::Expr arg,
const Analyzer::Constant pattern,
const char  escape_char,
const CompilationOptions co 
)
private

Definition at line 900 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().

904  {
906  const auto cast_oper = std::dynamic_pointer_cast<Analyzer::UOper>(pattern_arg);
907  if (!cast_oper) {
908  return nullptr;
909  }
910  CHECK(cast_oper);
911  CHECK_EQ(kCAST, cast_oper->get_optype());
912  const auto dict_regexp_arg = cast_oper->get_own_operand();
913  const auto& dict_regexp_arg_ti = dict_regexp_arg->get_type_info();
914  CHECK(dict_regexp_arg_ti.is_string());
915  CHECK_EQ(kENCODING_DICT, dict_regexp_arg_ti.get_compression());
916  const auto& dict_key = dict_regexp_arg_ti.getStringDictKey();
917  const auto sdp = executor()->getStringDictionaryProxy(
918  dict_key, executor()->getRowSetMemoryOwner(), true);
919  if (sdp->storageEntryCount() > 15000000) {
920  return nullptr;
921  }
922  if (sdp->getDictKey().isTransientDict()) {
923  // If we have a literal dictionary it was a product
924  // of string ops applied to none-encoded strings, and
925  // will not be populated at codegen-time, so we
926  // cannot use the fast path
927 
928  // Todo(todd): Once string ops support non-string producting
929  // operators (like regexp_like), these operators can be chained
930  // and we can avoid the string translation
931  return nullptr;
932  }
933  const auto string_oper =
934  dynamic_cast<const Analyzer::StringOper*>(dict_regexp_arg.get());
935  if (string_oper) {
936  pre_translate_string_ops(string_oper, executor());
937  }
938  const auto& pattern_ti = pattern->get_type_info();
939  CHECK(pattern_ti.is_string());
940  CHECK_EQ(kENCODING_NONE, pattern_ti.get_compression());
941  const auto& pattern_datum = pattern->get_constval();
942  const auto& pattern_str = *pattern_datum.stringval;
943  const auto matching_ids = sdp->getRegexpLike(pattern_str, escape_char);
944  // InIntegerSet requires 64-bit values
945  std::vector<int64_t> matching_ids_64(matching_ids.size());
946  std::copy(matching_ids.begin(), matching_ids.end(), matching_ids_64.begin());
947  const auto in_values = std::make_shared<Analyzer::InIntegerSet>(
948  dict_regexp_arg, matching_ids_64, dict_regexp_arg_ti.get_notnull());
949  return codegen(in_values.get(), co);
950 }
#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:48
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: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
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 759 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().

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

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK, CHECK_EQ, codegenSkipOverflowCheckForNull(), CgenState::context_, CgenState::current_func_, CgenState::emitCall(), Executor::ERR_DIV_BY_ZERO, Executor::ERR_OVERFLOW_OR_UNDERFLOW, 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().

436  {
438  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
439  if (ti.is_decimal()) {
440  if (upscale) {
441  CHECK(lhs_lv->getType()->isIntegerTy());
442  const auto scale_lv =
443  llvm::ConstantInt::get(lhs_lv->getType(), exp_to_scale(ti.get_scale()));
444 
445  lhs_lv = cgen_state_->ir_builder_.CreateSExt(
446  lhs_lv, get_int_type(64, cgen_state_->context_));
447  llvm::Value* chosen_max{nullptr};
448  llvm::Value* chosen_min{nullptr};
449  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(8, true);
450  auto decimal_div_ok = llvm::BasicBlock::Create(
451  cgen_state_->context_, "decimal_div_ok", cgen_state_->current_func_);
452  if (!null_check_suffix.empty()) {
453  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, decimal_div_ok, ti);
454  }
455  auto decimal_div_fail = llvm::BasicBlock::Create(
456  cgen_state_->context_, "decimal_div_fail", cgen_state_->current_func_);
457  auto lhs_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() /
458  exp_to_scale(ti.get_scale());
459  auto lhs_max_lv =
460  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), lhs_max);
461  llvm::Value* detected{nullptr};
462  if (ti.get_notnull()) {
463  detected = cgen_state_->ir_builder_.CreateICmpSGT(lhs_lv, lhs_max_lv);
464  } else {
465  detected = toBool(cgen_state_->emitCall(
466  "gt_" + numeric_type_name(ti) + "_nullable",
467  {lhs_lv,
468  lhs_max_lv,
471  }
472  cgen_state_->ir_builder_.CreateCondBr(detected, decimal_div_fail, decimal_div_ok);
473 
474  cgen_state_->ir_builder_.SetInsertPoint(decimal_div_fail);
475  cgen_state_->ir_builder_.CreateRet(
477 
478  cgen_state_->ir_builder_.SetInsertPoint(decimal_div_ok);
479 
480  lhs_lv = null_typename.empty()
481  ? cgen_state_->ir_builder_.CreateMul(lhs_lv, scale_lv)
483  "mul_" + numeric_type_name(ti) + null_check_suffix,
484  {lhs_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(ti))});
485  }
486  }
487  if (g_null_div_by_zero) {
488  llvm::Value* null_lv{nullptr};
489  if (ti.is_fp()) {
490  null_lv = ti.get_type() == kFLOAT ? cgen_state_->llFp(NULL_FLOAT)
492  } else {
493  null_lv = cgen_state_->llInt(inline_int_null_val(ti));
494  }
495  return cgen_state_->emitCall("safe_div_" + numeric_type_name(ti),
496  {lhs_lv, rhs_lv, null_lv});
497  }
499  auto div_ok = llvm::BasicBlock::Create(
501  if (!null_check_suffix.empty()) {
502  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, div_ok, ti);
503  }
504  auto div_zero = llvm::BasicBlock::Create(
506  auto zero_const = rhs_lv->getType()->isIntegerTy()
507  ? llvm::ConstantInt::get(rhs_lv->getType(), 0, true)
508  : llvm::ConstantFP::get(rhs_lv->getType(), 0.);
509  cgen_state_->ir_builder_.CreateCondBr(
510  zero_const->getType()->isFloatingPointTy()
511  ? cgen_state_->ir_builder_.CreateFCmp(
512  llvm::FCmpInst::FCMP_ONE, rhs_lv, zero_const)
513  : cgen_state_->ir_builder_.CreateICmp(
514  llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
515  div_ok,
516  div_zero);
517  cgen_state_->ir_builder_.SetInsertPoint(div_ok);
518  auto ret =
519  zero_const->getType()->isIntegerTy()
520  ? (null_typename.empty()
521  ? cgen_state_->ir_builder_.CreateSDiv(lhs_lv, rhs_lv)
523  "div_" + null_typename + null_check_suffix,
524  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))}))
525  : (null_typename.empty()
526  ? cgen_state_->ir_builder_.CreateFDiv(lhs_lv, rhs_lv)
528  "div_" + null_typename + null_check_suffix,
529  {lhs_lv,
530  rhs_lv,
533  cgen_state_->ir_builder_.SetInsertPoint(div_zero);
535  cgen_state_->ir_builder_.SetInsertPoint(div_ok);
536  return ret;
537 }
#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:571
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:91
static const int32_t ERR_DIV_BY_ZERO
Definition: Execute.h:1615
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
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
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:343
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:568
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:1034
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:2828
#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:2794
CgenState * cgen_state_
bool is_fp() const
Definition: sqltypes.h:571
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:2796
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 132 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().

134  {
136  const auto lhs = bin_oper->get_left_operand();
137  const auto rhs = bin_oper->get_right_operand();
138  const auto& lhs_type = lhs->get_type_info();
139  const auto& rhs_type = rhs->get_type_info();
140  const auto fp_typename = numeric_type_name(lhs_type);
141  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
142  llvm::ConstantFP* fp_null{lhs_type.get_type() == kFLOAT
145  switch (bin_oper->get_optype()) {
146  case kMINUS:
147  return null_check_suffix.empty()
148  ? cgen_state_->ir_builder_.CreateFSub(lhs_lv, rhs_lv)
149  : cgen_state_->emitCall("sub_" + fp_typename + null_check_suffix,
150  {lhs_lv, rhs_lv, fp_null});
151  case kPLUS:
152  return null_check_suffix.empty()
153  ? cgen_state_->ir_builder_.CreateFAdd(lhs_lv, rhs_lv)
154  : cgen_state_->emitCall("add_" + fp_typename + null_check_suffix,
155  {lhs_lv, rhs_lv, fp_null});
156  case kMULTIPLY:
157  return null_check_suffix.empty()
158  ? cgen_state_->ir_builder_.CreateFMul(lhs_lv, rhs_lv)
159  : cgen_state_->emitCall("mul_" + fp_typename + null_check_suffix,
160  {lhs_lv, rhs_lv, fp_null});
161  case kDIVIDE:
162  return codegenDiv(lhs_lv,
163  rhs_lv,
164  null_check_suffix.empty() ? "" : fp_typename,
165  null_check_suffix,
166  lhs_type);
167  default:
168  CHECK(false);
169  }
170  CHECK(false);
171  return nullptr;
172 }
#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:40
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:1678
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:39
#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:2615
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:48
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:2893
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:2617
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:2613

+ 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:2615
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
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
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)
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:2617
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:975
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:2615
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:2617
#define CHECK(condition)
Definition: Logger.h:291
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
Definition: LogicalIR.cpp:412
int get_physical_coord_cols() const
Definition: sqltypes.h:449

+ 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:2615
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:2617
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:2613
bool is_decimal() const
Definition: sqltypes.h:568

+ 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 369 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().

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

26  {
27  CHECK(byte_stream);
28 
29  const auto key = std::make_pair(byte_stream, pos);
30  auto cache_itr = cgen_state->array_load_cache_.find(key);
31  if (cache_itr != cgen_state->array_load_cache_.end()) {
32  return cache_itr->second;
33  }
34  const bool is_nullable = !ti.get_notnull();
35  CHECK(ti.get_type() == kPOINT); // TODO: lift this
36 
37  auto pt_arr_buf =
38  cgen_state->emitExternalCall("array_buff",
39  llvm::Type::getInt8PtrTy(cgen_state->context_),
40  {key.first, key.second});
41  llvm::Value* pt_is_null{nullptr};
42  if (is_nullable) {
43  pt_is_null = cgen_state->emitExternalCall("point_coord_array_is_null",
44  llvm::Type::getInt1Ty(cgen_state->context_),
45  {key.first, key.second});
46  }
47  ArrayLoadCodegen arr_load{pt_arr_buf, nullptr, pt_is_null};
48  cgen_state->array_load_cache_.insert(std::make_pair(key, arr_load));
49  return arr_load;
50 }
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 261 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().

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

55  {
56  auto generate_column_lvs = [this, geo_col_var, &co](const int column_id) {
57  auto column_key = geo_col_var->getColumnKey();
58  column_key.column_id = column_id;
59 
60  auto cd = get_column_descriptor(column_key);
61  CHECK(cd);
62 
63  const auto col_var =
64  Analyzer::ColumnVar(cd->columnType, column_key, geo_col_var->get_rte_idx());
65  const auto lv_vec = codegen(&col_var, /*fetch_columns=*/true, co);
66  CHECK_EQ(lv_vec.size(), size_t(1)); // ptr
67  return lv_vec;
68  };
69 
70  const auto& ti = geo_col_var->get_type_info();
71  switch (ti.get_type()) {
72  case kPOINT:
73  case kLINESTRING:
74  case kMULTILINESTRING:
75  case kPOLYGON:
76  case kMULTIPOLYGON: {
77  std::vector<llvm::Value*> geo_lvs;
78  // iterate over physical columns
79  for (int i = 0; i < ti.get_physical_coord_cols(); i++) {
80  const auto column_id = geo_col_var->getColumnKey().column_id + 1 + i;
81  const auto lvs = generate_column_lvs(column_id);
82  CHECK_EQ(lvs.size(), size_t(1)); // expecting ptr for each column
83  geo_lvs.insert(geo_lvs.end(), lvs.begin(), lvs.end());
84  }
85 
86  return geo_lvs;
87  }
88  default:
89  UNREACHABLE() << geo_col_var->toString();
90  }
91  UNREACHABLE();
92  return {};
93 }
#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 109 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().

111  {
113 
114  std::vector<llvm::Value*> ret;
115  for (size_t i = 0; i < geo_constant->physicalCols(); i++) {
116  auto physical_constant = geo_constant->makePhysicalConstant(i);
117  auto operand_lvs = codegen(physical_constant.get(), /*fetch_columns=*/true, co);
118  CHECK_EQ(operand_lvs.size(), size_t(2));
119  auto array_buff_lv = operand_lvs[0];
120  if (i > 0) {
121  array_buff_lv = cgen_state_->ir_builder_.CreateBitCast(
122  operand_lvs[0], llvm::Type::getInt8PtrTy(cgen_state_->context_));
123  }
124  ret.push_back(array_buff_lv);
125  ret.push_back(operand_lvs[1]);
126  }
127  return ret;
128 }
#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:4064
size_t physicalCols() const
Definition: Analyzer.cpp:4059

+ 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 95 of file GeoIR.cpp.

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

Referenced by codegen().

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

+ 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 147 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().

149  {
151 
152  if (geo_operator->getName() == "ST_X" || geo_operator->getName() == "ST_Y") {
153  const auto key = geo_operator->toString();
154  auto geo_target_cache_it = cgen_state_->geo_target_cache_.find(key);
155  if (geo_target_cache_it != cgen_state_->geo_target_cache_.end()) {
156  return {geo_target_cache_it->second};
157  }
158  }
159 
160  auto op_codegen = spatial_type::Codegen::init(geo_operator);
161  CHECK(op_codegen);
162  // we fetch all physical columns, so we sync the logical geo column w/ it
164 
165  std::vector<llvm::Value*> load_lvs;
166  std::vector<llvm::Value*> pos_lvs;
167  for (size_t i = 0; i < op_codegen->size(); i++) {
168  auto intermediate_lvs =
169  codegen(op_codegen->getOperand(i), /*fetch_columns=*/true, co);
170  load_lvs.insert(load_lvs.end(), intermediate_lvs.begin(), intermediate_lvs.end());
171  pos_lvs.push_back(posArg(op_codegen->getOperand(i)));
172  }
173 
174  auto [arg_lvs, null_lv] = op_codegen->codegenLoads(load_lvs, pos_lvs, cgen_state_);
175 
176  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen =
177  op_codegen->getNullCheckCodegen(null_lv, cgen_state_, executor());
178  return op_codegen->codegen(arg_lvs, nullcheck_codegen.get(), cgen_state_, co);
179 }
void mark_logical_column_to_fetch(const Analyzer::GeoOperator *geo_operator, PlanState *plan_state)
Definition: GeoIR.cpp:131
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:3167
#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:4154
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 483 of file GeoIR.cpp.

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

Referenced by codegenGeoBinOper(), and codegenGeoUOper().

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

References AUTOMATIC_IR_METADATA, cgen_state_, CgenState::context_, CgenState::current_func_, CgenState::emitExternalCall(), Executor::ERR_GEOS, 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().

453  {
455  auto i8_type = get_int_type(8, cgen_state_->context_);
456  auto result = cgen_state_->ir_builder_.CreateAlloca(i8_type, nullptr, "result");
457  argument_list.emplace_back(result);
458 
459  // Generate call to GEOS wrapper
460  cgen_state_->needs_geos_ = true;
461  auto status_lv = cgen_state_->emitExternalCall(
462  func, llvm::Type::getInt1Ty(cgen_state_->context_), argument_list);
463  // Need to check the status and throw an error if this call has failed.
464  llvm::BasicBlock* geos_pred_ok_bb{nullptr};
465  llvm::BasicBlock* geos_pred_fail_bb{nullptr};
466  geos_pred_ok_bb = llvm::BasicBlock::Create(
467  cgen_state_->context_, "geos_pred_ok_bb", cgen_state_->current_func_);
468  geos_pred_fail_bb = llvm::BasicBlock::Create(
469  cgen_state_->context_, "geos_pred_fail_bb", cgen_state_->current_func_);
470  if (!status_lv) {
471  status_lv = cgen_state_->llBool(false);
472  }
473  cgen_state_->ir_builder_.CreateCondBr(status_lv, geos_pred_ok_bb, geos_pred_fail_bb);
474  cgen_state_->ir_builder_.SetInsertPoint(geos_pred_fail_bb);
477  cgen_state_->ir_builder_.SetInsertPoint(geos_pred_ok_bb);
478  auto res = cgen_state_->ir_builder_.CreateLoad(
479  result->getType()->getPointerElementType(), result);
480  return {res};
481 }
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
static const int32_t ERR_GEOS
Definition: Execute.h:1629
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 181 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().

183  {
186  if (geo_expr->getOp() != Geospatial::GeoBase::GeoOp::kPROJECTION) {
187  throw QueryMustRunOnCpu();
188  }
189  }
190 
191  auto argument_list = codegenGeoArgs(geo_expr->getArgs0(), co);
192 
193  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kPROJECTION) {
194  return argument_list;
195  }
196 
197 #ifndef ENABLE_GEOS
198  throw std::runtime_error("Geo operation requires GEOS support.");
199 #endif
200 
201  // Basic set of arguments is currently common to all Geos_* func invocations:
202  // op kind, type of the first geo arg0, geo arg0 components
203  std::string func = "Geos_Wkb"s;
204 
205  if (geo_expr->getTypeInfo0().transforms() || geo_expr->get_type_info().transforms()) {
206  // If there is a transform on the argument and/or on the result of the operation,
207  // verify that the argument's output srid is equal to result's input srid
208  if (geo_expr->getTypeInfo0().get_output_srid() !=
209  geo_expr->get_type_info().get_input_srid()) {
210  throw std::runtime_error("GEOS runtime: input/output srids have to match.");
211  }
212  }
213  // Prepend arg0 geo SQLType
214  argument_list.insert(
215  argument_list.begin(),
216  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_type())));
217  // Prepend geo expr op
218  argument_list.insert(argument_list.begin(),
219  cgen_state_->llInt(static_cast<int>(geo_expr->getOp())));
220  for (auto i = 3; i > geo_expr->getTypeInfo0().get_physical_coord_cols(); i--) {
221  argument_list.insert(argument_list.end(),
222  llvm::ConstantPointerNull::get(
223  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
224  argument_list.insert(argument_list.end(), cgen_state_->llInt(int64_t(0)));
225  }
226  // Append geo expr compression
227  argument_list.insert(
228  argument_list.end(),
229  cgen_state_->llInt(static_cast<int>(
231  // Append geo expr input srid
232  argument_list.insert(
233  argument_list.end(),
234  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_input_srid())));
235  // Append geo expr output srid
236  argument_list.insert(
237  argument_list.end(),
238  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_output_srid())));
239 
240  // Deal with unary geo predicates
241  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kISEMPTY ||
243  return codegenGeosPredicateCall(func, argument_list, co);
244  }
245 
246  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kCONVEXHULL) {
247  func += "_double"s; // Use same interface as ST_ConcaveHull, with a dummy double
248 
249  // Insert that dummy double arg
250  argument_list.insert(argument_list.end(), cgen_state_->llFp(double(0)));
251 
252  auto result_srid = cgen_state_->llInt(geo_expr->get_type_info().get_output_srid());
253 
254  return codegenGeosConstructorCall(func, argument_list, result_srid, co);
255  }
256 
257  throw std::runtime_error("Unsupported unary geo operation.");
258  return {};
259 }
const SQLTypeInfo getTypeInfo0() const
Definition: Analyzer.h:2931
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:2932
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:483
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:450
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:369
Geospatial::GeoBase::GeoOp getOp() const
Definition: Analyzer.h:2930
bool transforms() const
Definition: sqltypes.h:624
int get_physical_coord_cols() const
Definition: sqltypes.h:449
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(), InValuesBitmap::codegen(), codegen(), and CodegenUtil::createPtrWithHoistedMemoryAddr().

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
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
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:577
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:526
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:565
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
bool is_timeinterval() const
Definition: sqltypes.h:592
bool is_boolean() const
Definition: sqltypes.h:580
llvm::IRBuilder query_func_entry_ir_builder_
Definition: CgenState.h:409
#define AUTOMATIC_IR_METADATA(CGENSTATE)
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:298
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:595
bool is_string() const
Definition: sqltypes.h:559
bool is_decimal() const
Definition: sqltypes.h:568
SQLTypes get_phys_int_type(const size_t byte_sz)
Definition: ColumnIR.cpp:429
bool is_array() const
Definition: sqltypes.h:583

+ 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:595
bool is_string() const
Definition: sqltypes.h:559
bool is_array() const
Definition: sqltypes.h:583

+ 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 75 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().

78  {
80  const auto lhs = bin_oper->get_left_operand();
81  const auto rhs = bin_oper->get_right_operand();
82  const auto& lhs_type = lhs->get_type_info();
83  const auto& rhs_type = rhs->get_type_info();
84  const auto int_typename = numeric_or_time_interval_type_name(lhs_type, rhs_type);
85  const auto null_check_suffix = get_null_check_suffix(lhs_type, rhs_type);
86  const auto& oper_type = rhs_type.is_timeinterval() ? rhs_type : lhs_type;
87  switch (bin_oper->get_optype()) {
88  case kMINUS:
89  return codegenSub(bin_oper,
90  lhs_lv,
91  rhs_lv,
92  null_check_suffix.empty() ? "" : int_typename,
93  null_check_suffix,
94  oper_type,
95  co);
96  case kPLUS:
97  return codegenAdd(bin_oper,
98  lhs_lv,
99  rhs_lv,
100  null_check_suffix.empty() ? "" : int_typename,
101  null_check_suffix,
102  oper_type,
103  co);
104  case kMULTIPLY:
105  return codegenMul(bin_oper,
106  lhs_lv,
107  rhs_lv,
108  null_check_suffix.empty() ? "" : int_typename,
109  null_check_suffix,
110  oper_type,
111  co);
112  case kDIVIDE:
113  return codegenDiv(lhs_lv,
114  rhs_lv,
115  null_check_suffix.empty() ? "" : int_typename,
116  null_check_suffix,
117  oper_type);
118  case kMODULO:
119  return codegenMod(lhs_lv,
120  rhs_lv,
121  null_check_suffix.empty() ? "" : int_typename,
122  null_check_suffix,
123  oper_type);
124  default:
125  CHECK(false);
126  }
127  CHECK(false);
128  return nullptr;
129 }
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:40
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:1678
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
Definition: sqldefs.h:39
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:71
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:73
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
int64_t bigintval
Definition: Datum.h:74
int16_t smallintval
Definition: Datum.h:72
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 380 of file LogicalIR.cpp.

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

Referenced by codegen().

381  {
383  const auto operand = uoper->get_operand();
384  if (dynamic_cast<const Analyzer::Constant*>(operand) &&
385  dynamic_cast<const Analyzer::Constant*>(operand)->get_is_null()) {
386  // for null constants, short-circuit to true
387  return llvm::ConstantInt::get(get_int_type(1, cgen_state_->context_), 1);
388  }
389  const auto& ti = operand->get_type_info();
390  CHECK(ti.is_integer() || ti.is_boolean() || ti.is_decimal() || ti.is_time() ||
391  ti.is_string() || ti.is_fp() || ti.is_array() || ti.is_geometry());
392  // if the type is inferred as non null, short-circuit to false
393  if (ti.get_notnull()) {
394  return llvm::ConstantInt::get(get_int_type(1, cgen_state_->context_), 0);
395  }
396  llvm::Value* operand_lv = codegen(operand, true, co).front();
397  // NULL-check array or geo's coords array
398  if (ti.is_array() || ti.is_geometry()) {
399  // POINT [un]compressed coord check requires custom checker and chunk iterator
400  // Non-POINT NULL geographies will have a normally encoded null coord array
401  auto fname =
402  (ti.get_type() == kPOINT) ? "point_coord_array_is_null" : "array_is_null";
404  fname, get_int_type(1, cgen_state_->context_), {operand_lv, posArg(operand)});
405  } else if (ti.is_none_encoded_string()) {
406  operand_lv = cgen_state_->ir_builder_.CreateExtractValue(operand_lv, 0);
407  operand_lv = cgen_state_->castToTypeIn(operand_lv, sizeof(int64_t) * 8);
408  }
409  return codegenIsNullNumber(operand_lv, ti);
410 }
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)
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
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:412

+ 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 412 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().

413  {
415  if (ti.is_fp()) {
416  return cgen_state_->ir_builder_.CreateFCmp(llvm::FCmpInst::FCMP_OEQ,
417  operand_lv,
418  ti.get_type() == kFLOAT
421  }
422  return cgen_state_->ir_builder_.CreateICmp(
423  llvm::ICmpInst::ICMP_EQ, operand_lv, cgen_state_->inlineIntNull(ti));
424 }
#define NULL_DOUBLE
CgenState * cgen_state_
#define NULL_FLOAT
bool is_fp() const
Definition: sqltypes.h:571
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::string &  model_name,
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().

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

299  {
301  const auto optype = bin_oper->get_optype();
302  CHECK(IS_LOGIC(optype));
303 
304  if (llvm::Value* short_circuit = codegenLogicalShortCircuit(bin_oper, co)) {
305  return short_circuit;
306  }
307 
308  const auto lhs = bin_oper->get_left_operand();
309  const auto rhs = bin_oper->get_right_operand();
310  auto lhs_lv = codegen(lhs, true, co).front();
311  auto rhs_lv = codegen(rhs, true, co).front();
312  const auto& ti = bin_oper->get_type_info();
313  if (ti.get_notnull()) {
314  switch (optype) {
315  case kAND:
316  return cgen_state_->ir_builder_.CreateAnd(toBool(lhs_lv), toBool(rhs_lv));
317  case kOR:
318  return cgen_state_->ir_builder_.CreateOr(toBool(lhs_lv), toBool(rhs_lv));
319  default:
320  CHECK(false);
321  }
322  }
323  CHECK(lhs_lv->getType()->isIntegerTy(1) || lhs_lv->getType()->isIntegerTy(8));
324  CHECK(rhs_lv->getType()->isIntegerTy(1) || rhs_lv->getType()->isIntegerTy(8));
325  if (lhs_lv->getType()->isIntegerTy(1)) {
326  lhs_lv = cgen_state_->castToTypeIn(lhs_lv, 8);
327  }
328  if (rhs_lv->getType()->isIntegerTy(1)) {
329  rhs_lv = cgen_state_->castToTypeIn(rhs_lv, 8);
330  }
331  switch (optype) {
332  case kAND:
333  return cgen_state_->emitCall("logical_and",
334  {lhs_lv, rhs_lv, cgen_state_->inlineIntNull(ti)});
335  case kOR:
336  return cgen_state_->emitCall("logical_or",
337  {lhs_lv, rhs_lv, cgen_state_->inlineIntNull(ti)});
338  default:
339  abort();
340  }
341 }
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:150
#define IS_LOGIC(X)
Definition: sqldefs.h:61
CgenState * cgen_state_
const Expr * get_right_operand() const
Definition: Analyzer.h:456
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
Definition: sqldefs.h:37
SQLOps get_optype() const
Definition: Analyzer.h:452
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:65
Definition: sqldefs.h:36
#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:343
#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:196

+ 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 362 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().

363  {
365  const auto optype = uoper->get_optype();
366  CHECK_EQ(kNOT, optype);
367  const auto operand = uoper->get_operand();
368  const auto& operand_ti = operand->get_type_info();
369  CHECK(operand_ti.is_boolean());
370  const auto operand_lv = codegen(operand, true, co).front();
371  CHECK(operand_lv->getType()->isIntegerTy());
372  const bool not_null = (operand_ti.get_notnull() || is_qualified_bin_oper(operand));
373  CHECK(not_null || operand_lv->getType()->isIntegerTy(8));
374  return not_null
375  ? cgen_state_->ir_builder_.CreateNot(toBool(operand_lv))
377  "logical_not", {operand_lv, cgen_state_->inlineIntNull(operand_ti)});
378 }
#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:355
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:343
#define CHECK(condition)
Definition: Logger.h:291
Definition: sqldefs.h:38
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 196 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().

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

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

Referenced by codegenIntArith().

600  {
602  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
603  CHECK(ti.is_integer());
605  // Generate control flow for division by zero error handling.
606  auto mod_ok = llvm::BasicBlock::Create(
608  auto mod_zero = llvm::BasicBlock::Create(
610  auto zero_const = llvm::ConstantInt::get(rhs_lv->getType(), 0, true);
611  cgen_state_->ir_builder_.CreateCondBr(
612  cgen_state_->ir_builder_.CreateICmp(llvm::ICmpInst::ICMP_NE, rhs_lv, zero_const),
613  mod_ok,
614  mod_zero);
615  cgen_state_->ir_builder_.SetInsertPoint(mod_ok);
616  auto ret = null_typename.empty()
617  ? cgen_state_->ir_builder_.CreateSRem(lhs_lv, rhs_lv)
619  "mod_" + null_typename + null_check_suffix,
620  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
621  cgen_state_->ir_builder_.SetInsertPoint(mod_zero);
623  cgen_state_->ir_builder_.SetInsertPoint(mod_ok);
624  return ret;
625 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
CgenState * cgen_state_
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
static const int32_t ERR_DIV_BY_ZERO
Definition: Execute.h:1615
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
bool is_integer() const
Definition: sqltypes.h:565
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 359 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(), Executor::ERR_OVERFLOW_OR_UNDERFLOW, 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().

366  {
368  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
369  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
370  llvm::Value* chosen_max{nullptr};
371  llvm::Value* chosen_min{nullptr};
372  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
373  auto need_overflow_check =
374  !checkExpressionRanges(bin_oper,
375  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
376  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
377 
378  if (need_overflow_check && co.device_type == ExecutorDeviceType::CPU) {
380  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
381  }
382 
383  llvm::BasicBlock* mul_ok{nullptr};
384  llvm::BasicBlock* mul_fail{nullptr};
385  if (need_overflow_check) {
387  mul_ok = llvm::BasicBlock::Create(
389  if (!null_check_suffix.empty()) {
390  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, mul_ok, ti);
391  }
392  mul_fail = llvm::BasicBlock::Create(
394  auto mul_check = llvm::BasicBlock::Create(
396  auto const_zero = llvm::ConstantInt::get(rhs_lv->getType(), 0, true);
397  cgen_state_->ir_builder_.CreateCondBr(
398  cgen_state_->ir_builder_.CreateICmpEQ(rhs_lv, const_zero), mul_ok, mul_check);
399  cgen_state_->ir_builder_.SetInsertPoint(mul_check);
400  auto rhs_is_negative_lv = cgen_state_->ir_builder_.CreateICmpSLT(rhs_lv, const_zero);
401  auto positive_rhs_lv = cgen_state_->ir_builder_.CreateSelect(
402  rhs_is_negative_lv, cgen_state_->ir_builder_.CreateNeg(rhs_lv), rhs_lv);
403  auto adjusted_lhs_lv = cgen_state_->ir_builder_.CreateSelect(
404  rhs_is_negative_lv, cgen_state_->ir_builder_.CreateNeg(lhs_lv), lhs_lv);
405  auto detected = cgen_state_->ir_builder_.CreateOr( // overflow
406  cgen_state_->ir_builder_.CreateICmpSGT(
407  adjusted_lhs_lv,
408  cgen_state_->ir_builder_.CreateSDiv(chosen_max, positive_rhs_lv)),
409  // underflow
410  cgen_state_->ir_builder_.CreateICmpSLT(
411  adjusted_lhs_lv,
412  cgen_state_->ir_builder_.CreateSDiv(chosen_min, positive_rhs_lv)));
413  cgen_state_->ir_builder_.CreateCondBr(detected, mul_fail, mul_ok);
414  cgen_state_->ir_builder_.SetInsertPoint(mul_ok);
415  }
416  const auto ret =
417  null_check_suffix.empty()
418  ? cgen_state_->ir_builder_.CreateMul(lhs_lv, rhs_lv)
420  "mul_" + null_typename + null_check_suffix,
421  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
422  if (need_overflow_check) {
423  cgen_state_->ir_builder_.SetInsertPoint(mul_fail);
424  cgen_state_->ir_builder_.CreateRet(
426  cgen_state_->ir_builder_.SetInsertPoint(mul_ok);
427  }
428  return ret;
429 }
#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:565
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)
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
bool is_timeinterval() const
Definition: sqltypes.h:592
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:568
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:69
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)
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
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::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:1055
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 558 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().

562  {
564  const auto& rhs_ti = rhs->get_type_info();
565  const Analyzer::Expr* arr_expr{rhs};
566  if (dynamic_cast<const Analyzer::UOper*>(rhs)) {
567  const auto cast_arr = static_cast<const Analyzer::UOper*>(rhs);
568  CHECK_EQ(kCAST, cast_arr->get_optype());
569  arr_expr = cast_arr->get_operand();
570  }
571  const auto& arr_ti = arr_expr->get_type_info();
572  const auto& elem_ti = arr_ti.get_elem_type();
573  auto rhs_lvs = codegen(arr_expr, true, co);
574  CHECK_NE(kONE, qualifier);
575  std::string fname{std::string("array_") + (qualifier == kANY ? "any" : "all") + "_" +
576  icmp_arr_name(optype)};
577  const auto& target_ti = rhs_ti.get_elem_type();
578  const bool is_real_string{target_ti.is_string() &&
579  target_ti.get_compression() != kENCODING_DICT};
580  if (is_real_string) {
581  if (g_cluster) {
582  throw std::runtime_error(
583  "Comparison between a dictionary-encoded and a none-encoded string not "
584  "supported for distributed queries");
585  }
586  if (g_enable_watchdog) {
587  throw WatchdogException(
588  "Comparison between a dictionary-encoded and a none-encoded string would be "
589  "slow");
590  }
592  throw QueryMustRunOnCpu();
593  }
594  CHECK_EQ(kENCODING_NONE, target_ti.get_compression());
595  fname += "_str";
596  }
597  if (elem_ti.is_integer() || elem_ti.is_boolean() || elem_ti.is_string() ||
598  elem_ti.is_decimal()) {
599  fname += ("_" + numeric_type_name(elem_ti));
600  } else {
601  CHECK(elem_ti.is_fp());
602  fname += elem_ti.get_type() == kDOUBLE ? "_double" : "_float";
603  }
604  if (is_real_string) {
605  CHECK_EQ(size_t(3), lhs_lvs.size());
607  fname,
609  {rhs_lvs.front(),
610  posArg(arr_expr),
611  lhs_lvs[1],
612  lhs_lvs[2],
613  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
614  elem_ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true))),
615  cgen_state_->inlineIntNull(elem_ti)});
616  }
617  if (target_ti.is_integer() || target_ti.is_boolean() || target_ti.is_string() ||
618  target_ti.is_decimal()) {
619  fname += ("_" + numeric_type_name(target_ti));
620  } else {
621  CHECK(target_ti.is_fp());
622  fname += target_ti.get_type() == kDOUBLE ? "_double" : "_float";
623  }
625  fname,
627  {rhs_lvs.front(),
628  posArg(arr_expr),
629  lhs_lvs.front(),
630  elem_ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(elem_ti))
631  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(elem_ti))});
632 }
#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:48
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:71
#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:71
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:74
#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:69
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 343 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().

346  {
347  const auto lhs_is_null_lv = codegenIsNullNumber(lhs_lv, ti);
348  const auto has_null_operand_lv =
349  rhs_lv ? cgen_state_->ir_builder_.CreateOr(lhs_is_null_lv,
350  codegenIsNullNumber(rhs_lv, ti))
351  : lhs_is_null_lv;
352  auto operands_not_null = llvm::BasicBlock::Create(
353  cgen_state_->context_, "operands_not_null", cgen_state_->current_func_);
354  cgen_state_->ir_builder_.CreateCondBr(
355  has_null_operand_lv, no_overflow_bb, operands_not_null);
356  cgen_state_->ir_builder_.SetInsertPoint(operands_not_null);
357 }
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:412

+ 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 
390  // check if query is trying to compare a columnt against literal
391 
392  auto ir = codegenDictStrCmp(lhs, rhs, optype, co);
393  if (ir) {
394  return ir;
395  }
396  } else {
397  // Both operands don't share a dictionary
398  return nullptr;
399  }
400  }
401  return nullptr;
402 }
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:1678
#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 279 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(), Executor::ERR_OVERFLOW_OR_UNDERFLOW, 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().

285  {
287  CHECK_EQ(lhs_lv->getType(), rhs_lv->getType());
288  CHECK(ti.is_integer() || ti.is_decimal() || ti.is_timeinterval());
289  llvm::Value* chosen_max{nullptr};
290  llvm::Value* chosen_min{nullptr};
291  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
292  auto need_overflow_check =
293  !checkExpressionRanges(bin_oper,
294  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
295  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
296 
297  if (need_overflow_check && co.device_type == ExecutorDeviceType::CPU) {
299  bin_oper, lhs_lv, rhs_lv, null_check_suffix, ti);
300  }
301 
302  llvm::BasicBlock* sub_ok{nullptr};
303  llvm::BasicBlock* sub_fail{nullptr};
304  if (need_overflow_check) {
306  sub_ok = llvm::BasicBlock::Create(
308  if (!null_check_suffix.empty()) {
309  codegenSkipOverflowCheckForNull(lhs_lv, rhs_lv, sub_ok, ti);
310  }
311  sub_fail = llvm::BasicBlock::Create(
313  llvm::Value* detected{nullptr};
314  auto const_zero = llvm::ConstantInt::get(lhs_lv->getType(), 0, true);
315  auto overflow = cgen_state_->ir_builder_.CreateAnd(
316  cgen_state_->ir_builder_.CreateICmpSLT(
317  rhs_lv, const_zero), // sub going up, check the max
318  cgen_state_->ir_builder_.CreateICmpSGT(
319  lhs_lv, cgen_state_->ir_builder_.CreateAdd(chosen_max, rhs_lv)));
320  auto underflow = cgen_state_->ir_builder_.CreateAnd(
321  cgen_state_->ir_builder_.CreateICmpSGT(
322  rhs_lv, const_zero), // sub going down, check the min
323  cgen_state_->ir_builder_.CreateICmpSLT(
324  lhs_lv, cgen_state_->ir_builder_.CreateAdd(chosen_min, rhs_lv)));
325  detected = cgen_state_->ir_builder_.CreateOr(overflow, underflow);
326  cgen_state_->ir_builder_.CreateCondBr(detected, sub_fail, sub_ok);
327  cgen_state_->ir_builder_.SetInsertPoint(sub_ok);
328  }
329  auto ret = null_check_suffix.empty()
330  ? cgen_state_->ir_builder_.CreateSub(lhs_lv, rhs_lv)
332  "sub_" + null_typename + null_check_suffix,
333  {lhs_lv, rhs_lv, cgen_state_->llInt(inline_int_null_val(ti))});
334  if (need_overflow_check) {
335  cgen_state_->ir_builder_.SetInsertPoint(sub_fail);
336  cgen_state_->ir_builder_.CreateRet(
338  cgen_state_->ir_builder_.SetInsertPoint(sub_ok);
339  }
340  return ret;
341 }
#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:565
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)
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
bool is_timeinterval() const
Definition: sqltypes.h:592
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:568
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::string &  model_name,
const std::shared_ptr< AbstractMLModel > &  model,
const CompilationOptions co 
)
private

Definition at line 182 of file MLPredictCodegen.cpp.

References cgen_state_, CHECK, 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().

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

References AUTOMATIC_IR_METADATA, cgen_state_, CHECK_EQ, checkExpressionRanges(), codegen(), codegenSkipOverflowCheckForNull(), CgenState::context_, CgenState::current_func_, CgenState::emitCall(), Executor::ERR_OVERFLOW_OR_UNDERFLOW, 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().

653  {
655  CHECK_EQ(uoper->get_optype(), kUMINUS);
656  const auto operand_lv = codegen(uoper->get_operand(), true, co).front();
657  const auto& ti = uoper->get_type_info();
658  llvm::Value* chosen_max{nullptr};
659  llvm::Value* chosen_min{nullptr};
660  bool need_overflow_check = false;
661  if (ti.is_integer() || ti.is_decimal() || ti.is_timeinterval()) {
662  std::tie(chosen_max, chosen_min) = cgen_state_->inlineIntMaxMin(ti.get_size(), true);
663  need_overflow_check = !checkExpressionRanges(
664  uoper,
665  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
666  static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue());
667  }
668  llvm::BasicBlock* uminus_ok{nullptr};
669  llvm::BasicBlock* uminus_fail{nullptr};
670  if (need_overflow_check) {
672  uminus_ok = llvm::BasicBlock::Create(
674  if (!ti.get_notnull()) {
675  codegenSkipOverflowCheckForNull(operand_lv, nullptr, uminus_ok, ti);
676  }
677  uminus_fail = llvm::BasicBlock::Create(
678  cgen_state_->context_, "uminus_fail", cgen_state_->current_func_);
679  auto const_min = llvm::ConstantInt::get(
680  operand_lv->getType(),
681  static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue(),
682  true);
683  auto overflow = cgen_state_->ir_builder_.CreateICmpEQ(operand_lv, const_min);
684  cgen_state_->ir_builder_.CreateCondBr(overflow, uminus_fail, uminus_ok);
685  cgen_state_->ir_builder_.SetInsertPoint(uminus_ok);
686  }
687  auto ret =
688  ti.get_notnull()
689  ? (ti.is_fp() ? cgen_state_->ir_builder_.CreateFNeg(operand_lv)
690  : cgen_state_->ir_builder_.CreateNeg(operand_lv))
692  "uminus_" + numeric_type_name(ti) + "_nullable",
693  {operand_lv,
694  ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(ti))
695  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(ti))});
696  if (need_overflow_check) {
697  cgen_state_->ir_builder_.SetInsertPoint(uminus_fail);
698  cgen_state_->ir_builder_.CreateRet(
700  cgen_state_->ir_builder_.SetInsertPoint(uminus_ok);
701  }
702  return ret;
703 }
#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
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1621
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(), Executor::ERR_WIDTH_BUCKET_INVALID_ARGUMENT, 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(
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:33
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqldefs.h:71
static const int32_t ERR_WIDTH_BUCKET_INVALID_ARGUMENT
Definition: Execute.h:1630
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:343
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:419
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 111 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().

113  {
115  const auto& value_list = in_values->get_value_list();
116  const auto val_count = value_list.size();
117  const auto& ti = in_values->get_arg()->get_type_info();
118  if (!(ti.is_integer() || (ti.is_string() && ti.get_compression() == kENCODING_DICT))) {
119  return nullptr;
120  }
121  const auto sdp =
122  ti.is_string()
123  ? executor()->getStringDictionaryProxy(
124  ti.getStringDictKey(), executor()->getRowSetMemoryOwner(), true)
125  : nullptr;
126  if (val_count > 3) {
127  using ListIterator = decltype(value_list.begin());
128  std::vector<int64_t> values;
129  const auto needle_null_val = inline_int_null_val(ti);
130  const int worker_count = val_count > 10000 ? cpu_threads() : int(1);
131  std::vector<std::vector<int64_t>> values_set(worker_count, std::vector<int64_t>());
132  std::vector<std::future<bool>> worker_threads;
133  auto start_it = value_list.begin();
134  for (size_t i = 0,
135  start_val = 0,
136  stride = (val_count + worker_count - 1) / worker_count;
137  i < val_count && start_val < val_count;
138  ++i, start_val += stride, std::advance(start_it, stride)) {
139  auto end_it = start_it;
140  std::advance(end_it, std::min(stride, val_count - start_val));
141  const auto do_work = [&](std::vector<int64_t>& out_vals,
142  const ListIterator start,
143  const ListIterator end) -> bool {
144  for (auto val_it = start; val_it != end; ++val_it) {
145  const auto& in_val = *val_it;
146  const auto in_val_const =
147  dynamic_cast<const Analyzer::Constant*>(extract_cast_arg(in_val.get()));
148  if (!in_val_const) {
149  return false;
150  }
151  const auto& in_val_ti = in_val->get_type_info();
152  CHECK(in_val_ti == ti || get_nullable_type_info(in_val_ti) == ti);
153  if (ti.is_string()) {
154  CHECK(sdp);
155  const auto string_id =
156  in_val_const->get_is_null()
157  ? needle_null_val
158  : sdp->getIdOfString(*in_val_const->get_constval().stringval);
159  if (string_id != StringDictionary::INVALID_STR_ID) {
160  out_vals.push_back(string_id);
161  }
162  } else {
163  out_vals.push_back(CodeGenerator::codegenIntConst(in_val_const, cgen_state_)
164  ->getSExtValue());
165  }
166  }
167  return true;
168  };
169  if (worker_count > 1) {
170  worker_threads.push_back(std::async(
171  std::launch::async, do_work, std::ref(values_set[i]), start_it, end_it));
172  } else {
173  do_work(std::ref(values), start_it, end_it);
174  }
175  }
176  bool success = true;
177  for (auto& worker : worker_threads) {
178  success &= worker.get();
179  }
180  if (!success) {
181  return nullptr;
182  }
183  if (worker_count > 1) {
184  size_t total_val_count = 0;
185  for (auto& vals : values_set) {
186  total_val_count += vals.size();
187  }
188  values.reserve(total_val_count);
189  for (auto& vals : values_set) {
190  values.insert(values.end(), vals.begin(), vals.end());
191  }
192  }
193  try {
194  return std::make_unique<InValuesBitmap>(values,
195  needle_null_val,
199  executor()->deviceCount(co.device_type),
200  executor()->data_mgr_);
201  } catch (...) {
202  return nullptr;
203  }
204  }
205  return nullptr;
206 }
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:559
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:1482
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(), 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:2613
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 437 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().

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

References mark_function_never_inline().

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

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

+ Here is the call graph for this function:

+ 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 1482 of file NativeCodegen.cpp.

1484  {
1485  auto timer = DEBUG_TIMER(__func__);
1486  auto mem_buff = llvm::MemoryBuffer::getMemBuffer(cuda_llir, "", false);
1487 
1488  llvm::SMDiagnostic parse_error;
1489 
1490  auto llvm_module = llvm::parseIR(mem_buff->getMemBufferRef(), parse_error, context);
1491  if (!llvm_module) {
1492  LOG(IR) << "CodeGenerator::generatePTX:NVVM IR:\n" << cuda_llir << "\nEnd of NNVM IR";
1493  throw_parseIR_error(parse_error, "generatePTX", /* is_gpu= */ true);
1494  }
1495 
1496  llvm::SmallString<256> code_str;
1497  llvm::raw_svector_ostream formatted_os(code_str);
1498  CHECK(nvptx_target_machine);
1499  {
1500  llvm::legacy::PassManager ptxgen_pm;
1501  llvm_module->setDataLayout(nvptx_target_machine->createDataLayout());
1502 
1503 #if LLVM_VERSION_MAJOR >= 10
1504  nvptx_target_machine->addPassesToEmitFile(
1505  ptxgen_pm, formatted_os, nullptr, llvm::CGFT_AssemblyFile);
1506 #else
1507  nvptx_target_machine->addPassesToEmitFile(
1508  ptxgen_pm, formatted_os, nullptr, llvm::TargetMachine::CGFT_AssemblyFile);
1509 #endif
1510  ptxgen_pm.run(*llvm_module);
1511  }
1512 
1513 #if LLVM_VERSION_MAJOR >= 11
1514  return std::string(code_str);
1515 #else
1516  return code_str.str();
1517 #endif
1518 }
#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 705 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().

707  {
708  llvm::Intrinsic::ID fn_id{llvm::Intrinsic::not_intrinsic};
709  switch (bin_oper->get_optype()) {
710  case kMINUS:
711  fn_id = llvm::Intrinsic::ssub_with_overflow;
712  break;
713  case kPLUS:
714  fn_id = llvm::Intrinsic::sadd_with_overflow;
715  break;
716  case kMULTIPLY:
717  fn_id = llvm::Intrinsic::smul_with_overflow;
718  break;
719  default:
720  LOG(FATAL) << "unexpected arith with overflow optype: " << bin_oper->toString();
721  }
722 
723  return llvm::Intrinsic::getDeclaration(cgen_state_->module_, fn_id, type);
724 }
CgenState * cgen_state_
#define LOG(tag)
Definition: Logger.h:285
Definition: sqldefs.h:40
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:39

+ 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:69
bool is_constructed_point(const Analyzer::Expr *expr)
Definition: Execute.h:1699
Definition: sqldefs.h:48
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:559
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:583

+ 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 1522 of file NativeCodegen.cpp.

Referenced by ScalarCodeGenerator::generateNativeGPUCode().

1523  {
1524  auto timer = DEBUG_TIMER(__func__);
1525 
1526  std::lock_guard<std::mutex> lock(initialize_nvptx_mutex_);
1527 
1528  llvm::InitializeAllTargets();
1529  llvm::InitializeAllTargetMCs();
1530  llvm::InitializeAllAsmPrinters();
1531  std::string err;
1532  auto target = llvm::TargetRegistry::lookupTarget("nvptx64", err);
1533  if (!target) {
1534  LOG(FATAL) << err;
1535  }
1536  return std::unique_ptr<llvm::TargetMachine>(
1537  target->createTargetMachine("nvptx64-nvidia-cuda",
1539  "",
1540  llvm::TargetOptions(),
1541  llvm::Reloc::Static));
1542 }
#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 552 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().

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

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

1971  {
1972  auto timer = DEBUG_TIMER(__func__);
1973  std::unordered_set<llvm::Function*> live_funcs;
1974  live_funcs.insert(roots.begin(), roots.end());
1975  live_funcs.insert(leaves.begin(), leaves.end());
1976 
1977  if (auto F = llvm_module.getFunction("init_shared_mem_nop")) {
1978  live_funcs.insert(F);
1979  }
1980  if (auto F = llvm_module.getFunction("write_back_nop")) {
1981  live_funcs.insert(F);
1982  }
1983 
1984  for (const llvm::Function* F : roots) {
1985  for (const llvm::BasicBlock& BB : *F) {
1986  for (const llvm::Instruction& I : BB) {
1987  if (const llvm::CallInst* CI = llvm::dyn_cast<const llvm::CallInst>(&I)) {
1988  live_funcs.insert(CI->getCalledFunction());
1989  }
1990  }
1991  }
1992  }
1993 
1994  for (llvm::Function& F : llvm_module) {
1995  if (!live_funcs.count(&F) && !F.isDeclaration()) {
1996  F.setLinkage(llvm::GlobalValue::InternalLinkage);
1997  }
1998  }
1999 
2000  return live_funcs;
2001 }
#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:69
bool is_constructed_point(const Analyzer::Expr *expr)
Definition: Execute.h:1699
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:559
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:583

+ 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 157 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.

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

343  {
345  CHECK(lv->getType()->isIntegerTy());
346  if (static_cast<llvm::IntegerType*>(lv->getType())->getBitWidth() > 1) {
347  return cgen_state_->ir_builder_.CreateICmp(
348  llvm::ICmpInst::ICMP_SGT, lv, llvm::ConstantInt::get(lv->getType(), 0));
349  }
350  return lv;
351 }
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 669 of file CodeGenerator.h.

Member Data Documentation

CgenState* CodeGenerator::cgen_state_
protected

Definition at line 667 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().

Executor* CodeGenerator::executor_
private
std::mutex CodeGenerator::initialize_cpu_backend_mutex_
staticprivate

Definition at line 676 of file CodeGenerator.h.

Referenced by generateNativeCPUCode().

std::mutex CodeGenerator::initialize_nvptx_mutex_
staticprivate

Definition at line 673 of file CodeGenerator.h.


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