OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointN.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
20 
21 namespace spatial_type {
22 
23 class PointN : public Codegen {
24  public:
25  PointN(const Analyzer::GeoOperator* geo_operator) : Codegen(geo_operator) {
26  CHECK_EQ(operator_->size(), size_t(2));
27  // set is nullable to true, because an index outside of the linestring will return
28  // null
29  // note we could probably just set this based on the operator type, as the operator
30  // type needs to match
31  this->is_nullable_ = true;
32  }
33 
34  std::unique_ptr<CodeGenerator::NullCheckCodegen> getNullCheckCodegen(
35  llvm::Value* null_lv,
36  CgenState* cgen_state,
37  Executor* executor) final {
38  if (isNullable()) {
39  CHECK(null_lv);
40  return std::make_unique<CodeGenerator::NullCheckCodegen>(
41  cgen_state, executor, null_lv, getNullType(), getName() + "_nullcheck");
42  } else {
43  return nullptr;
44  }
45  }
46 
47  size_t size() const final { return 2; }
48 
49  SQLTypeInfo getNullType() const final {
50  // nullability is the expression `linestring is null OR size within bounds`
51  return SQLTypeInfo(kBOOLEAN);
52  }
53 
54  llvm::Value* codegenGeoSize(CgenState* cgen_state,
55  SQLTypeInfo const& geo_ti,
56  const std::vector<llvm::Value*>& arg_lvs,
57  const std::vector<llvm::Value*>& pos_lvs) {
58  llvm::Value* geo_size_lv{nullptr};
59  if (arg_lvs.size() == 2) {
60  const bool is_nullable = !geo_ti.get_notnull();
61  std::string size_fn_name = "array_size";
62  if (is_nullable) {
63  size_fn_name += "_nullable";
64  }
65 
66  uint32_t elem_sz = 1; // TINYINT coords array
67  std::vector<llvm::Value*> array_sz_args{
68  arg_lvs.front(), pos_lvs.front(), cgen_state->llInt(log2_bytes(elem_sz))};
69  if (is_nullable) {
70  array_sz_args.push_back(
71  cgen_state->llInt(static_cast<int32_t>(inline_int_null_value<int32_t>())));
72  }
73  geo_size_lv = cgen_state->emitExternalCall(
74  size_fn_name, get_int_type(32, cgen_state->context_), array_sz_args);
75  } else {
76  geo_size_lv = arg_lvs[1];
77  }
78  CHECK(geo_size_lv);
79  return geo_size_lv;
80  }
81 
82  llvm::Value* codegenIndexOutOfBoundCheck(CgenState* cgen_state,
83  llvm::Value* index_lv,
84  llvm::Value* geosize_lv) {
85  llvm::Value* is_null_lv = cgen_state->llBool(false);
86  is_null_lv = cgen_state->ir_builder_.CreateOr(
87  is_null_lv,
88  cgen_state->ir_builder_.CreateICmp(llvm::ICmpInst::ICMP_SLT,
89  index_lv,
90  cgen_state->llInt(static_cast<int32_t>(0))));
91  return cgen_state->ir_builder_.CreateOr(
92  is_null_lv,
93  cgen_state->ir_builder_.CreateICmp(
94  llvm::ICmpInst::ICMP_SGE,
95  cgen_state->ir_builder_.CreateMul(index_lv,
96  cgen_state->llInt(static_cast<int32_t>(8))),
97  geosize_lv));
98  }
99 
100  // returns arguments lvs and null lv
101  std::tuple<std::vector<llvm::Value*>, llvm::Value*> codegenLoads(
102  const std::vector<llvm::Value*>& arg_lvs,
103  const std::vector<llvm::Value*>& pos_lvs,
104  CgenState* cgen_state) final {
105  CHECK_EQ(pos_lvs.size(), size());
106  CHECK_EQ(pos_lvs.front(), pos_lvs.back());
107  auto operand = getOperand(0);
108  CHECK(operand);
109  const auto& geo_ti = operand->get_type_info();
110  CHECK(geo_ti.get_type() == kLINESTRING);
111 
112  auto& builder = cgen_state->ir_builder_;
113 
114  std::vector<llvm::Value*> array_operand_lvs;
115  CHECK(!arg_lvs.empty());
116  llvm::Value* raw_index_lv = arg_lvs.back();
117  llvm::Value* geo_size_lv = codegenGeoSize(cgen_state, geo_ti, arg_lvs, pos_lvs);
118  llvm::Value* pt_size_lv = cgen_state->llInt(16);
119  llvm::Value* num_pts_lv = builder.CreateUDiv(geo_size_lv, pt_size_lv);
120  llvm::Value* is_negative_lv =
121  builder.CreateICmpSLT(raw_index_lv, cgen_state->llInt(0));
122  llvm::Value* negative_raw_index_lv = builder.CreateAdd(raw_index_lv, num_pts_lv);
123  llvm::Value* positive_raw_index_lv =
124  builder.CreateSub(raw_index_lv, cgen_state->llInt(1));
125  raw_index_lv = builder.CreateSelect(
126  is_negative_lv, negative_raw_index_lv, positive_raw_index_lv);
127  raw_index_lv =
128  builder.CreateMul(raw_index_lv, cgen_state->llInt(static_cast<int32_t>(2)));
129  llvm::Value* is_null_lv =
130  codegenIndexOutOfBoundCheck(cgen_state, raw_index_lv, geo_size_lv);
131  if (arg_lvs.size() == 2) {
132  // col byte stream from column on disk
133  array_operand_lvs.push_back(
134  cgen_state->emitExternalCall("array_buff",
135  llvm::Type::getInt8PtrTy(cgen_state->context_),
136  {arg_lvs.front(), pos_lvs.front()}));
137  array_operand_lvs.push_back(geo_size_lv);
138  // convert the index to a byte index
139  raw_index_lv =
140  builder.CreateMul(raw_index_lv, cgen_state->llInt(static_cast<int32_t>(8)));
141  const auto input_is_null_lv = builder.CreateICmp(
142  llvm::ICmpInst::ICMP_EQ,
143  geo_size_lv,
144  cgen_state->llInt(static_cast<int32_t>(inline_int_null_value<int32_t>())));
145  is_null_lv = builder.CreateOr(is_null_lv, input_is_null_lv);
146  } else {
147  CHECK_EQ(arg_lvs.size(), size_t(3)); // ptr, size, index
148  array_operand_lvs.push_back(arg_lvs[0]);
149  array_operand_lvs.push_back(arg_lvs[1]);
150  }
151  array_operand_lvs.push_back(raw_index_lv);
152  return std::make_tuple(array_operand_lvs, is_null_lv);
153  }
154 
155  std::vector<llvm::Value*> codegen(const std::vector<llvm::Value*>& args,
156  CodeGenerator::NullCheckCodegen* nullcheck_codegen,
157  CgenState* cgen_state,
158  const CompilationOptions& co) final {
159  CHECK_EQ(args.size(), size_t(3)); // ptr, size, index
160  const auto& geo_ti = getOperand(0)->get_type_info();
161  CHECK(geo_ti.is_geometry());
162 
163  llvm::Value* array_buff_cast{nullptr};
164 
165  auto& builder = cgen_state->ir_builder_;
166  if (geo_ti.get_compression() == kENCODING_GEOINT) {
167  array_buff_cast = builder.CreateBitCast(
168  args.front(), llvm::Type::getInt32PtrTy(cgen_state->context_));
169  } else {
170  array_buff_cast = builder.CreateBitCast(
171  args.front(), llvm::Type::getDoublePtrTy(cgen_state->context_));
172  }
173 
174  const auto index_lv = args.back();
175  auto array_offset_lv = builder.CreateGEP(
176  array_buff_cast->getType()->getScalarType()->getPointerElementType(),
177  array_buff_cast,
178  index_lv,
179  operator_->getName() + "_Offset");
180  CHECK(nullcheck_codegen);
181  auto ret_lv = nullcheck_codegen->finalize(
182  llvm::ConstantPointerNull::get(
183  geo_ti.get_compression() == kENCODING_GEOINT
184  ? llvm::PointerType::get(llvm::Type::getInt32Ty(cgen_state->context_), 0)
185  : llvm::PointerType::get(llvm::Type::getDoubleTy(cgen_state->context_),
186  0)),
187  array_offset_lv);
188  const auto geo_size_lv = args[1];
189  return {ret_lv, geo_size_lv};
190  }
191 };
192 
193 } // namespace spatial_type
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::unique_ptr< CodeGenerator::NullCheckCodegen > getNullCheckCodegen(llvm::Value *null_lv, CgenState *cgen_state, Executor *executor) final
Definition: PointN.h:34
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
llvm::ConstantInt * llBool(const bool v) const
Definition: CgenState.h:263
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
SQLTypeInfo getNullType() const final
Definition: PointN.h:49
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
std::vector< llvm::Value * > codegen(const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) final
Definition: PointN.h:155
auto isNullable() const
Definition: Codegen.h:32
llvm::Value * codegenGeoSize(CgenState *cgen_state, SQLTypeInfo const &geo_ti, const std::vector< llvm::Value * > &arg_lvs, const std::vector< llvm::Value * > &pos_lvs)
Definition: PointN.h:54
const Analyzer::GeoOperator * operator_
Definition: Codegen.h:69
size_t size() const
Definition: Analyzer.cpp:4211
llvm::Value * codegenIndexOutOfBoundCheck(CgenState *cgen_state, llvm::Value *index_lv, llvm::Value *geosize_lv)
Definition: PointN.h:82
size_t size() const final
Definition: PointN.h:47
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
#define CHECK(condition)
Definition: Logger.h:291
virtual const Analyzer::Expr * getOperand(const size_t index)
Definition: Codegen.cpp:64
std::string getName() const
Definition: Codegen.h:36
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:198
std::tuple< std::vector< llvm::Value * >, llvm::Value * > codegenLoads(const std::vector< llvm::Value * > &arg_lvs, const std::vector< llvm::Value * > &pos_lvs, CgenState *cgen_state) final
Definition: PointN.h:101
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
PointN(const Analyzer::GeoOperator *geo_operator)
Definition: PointN.h:25