OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointAccessors.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 // ST_X and ST_Y
24 class PointAccessors : public Codegen {
25  public:
26  PointAccessors(const Analyzer::GeoOperator* geo_operator) : Codegen(geo_operator) {
27  CHECK_EQ(operator_->size(), size_t(1));
28  }
29 
30  size_t size() const final { return 1; }
31 
32  SQLTypeInfo getNullType() const final { return SQLTypeInfo(kBOOLEAN); }
33 
34  llvm::Value* codegenCmpEqNullptr(llvm::IRBuilder<>& builder, llvm::Value* arg_lv) {
35  auto* const ptr_type = llvm::dyn_cast<llvm::PointerType>(arg_lv->getType());
36  CHECK(ptr_type);
37  return builder.CreateICmpEQ(arg_lv, llvm::ConstantPointerNull::get(ptr_type));
38  }
39 
40  // returns arguments lvs and null lv
41  std::tuple<std::vector<llvm::Value*>, llvm::Value*> codegenLoads(
42  const std::vector<llvm::Value*>& arg_lvs,
43  const std::vector<llvm::Value*>& pos_lvs,
44  CgenState* cgen_state) final {
45  CHECK_EQ(pos_lvs.size(), size());
46  auto operand = getOperand(0);
47  CHECK(operand);
48  const auto& geo_ti = operand->get_type_info();
49  CHECK(geo_ti.is_geometry());
50  auto& builder = cgen_state->ir_builder_;
51 
52  llvm::Value* array_buff_ptr{nullptr};
53  llvm::Value* is_null{nullptr};
54  if (arg_lvs.size() == 1) {
55  if (dynamic_cast<const Analyzer::GeoExpr*>(operand)) {
56  is_null = codegenCmpEqNullptr(builder, arg_lvs.front());
57  return std::make_tuple(arg_lvs, is_null);
58  }
59  // col byte stream, get the array buffer ptr and is null attributes and cache
61  arg_lvs.front(), pos_lvs.front(), geo_ti, cgen_state);
62  array_buff_ptr = arr_load_lvs.buffer;
63  is_null = arr_load_lvs.is_null;
64  } else {
65  // ptr and size
66  CHECK_EQ(arg_lvs.size(), size_t(2));
67  if (dynamic_cast<const Analyzer::GeoOperator*>(operand)) {
68  if (geo_ti.get_type() == kPOINT && !geo_ti.is_variable_size()) {
69  char const* const fname = pointIsNullFunctionName(geo_ti);
70  is_null = cgen_state->emitCall(fname, {arg_lvs.front()});
71  } else {
72  // The above branch tests for both nullptr and null sentinel, whereas this
73  // branch only tests for nullptr. If not for this branch, the GeospatialTest
74  // LLVMOptimization test fails due to non-removal of the
75  // decompress_{x,y}_coord_geoint function call in the generated IR. See QE-1007.
76  is_null = codegenCmpEqNullptr(builder, arg_lvs.front());
77  }
78  }
79  // TODO: nulls from other types not yet supported
80  array_buff_ptr = arg_lvs.front();
81  }
82  CHECK(array_buff_ptr) << operator_->toString();
83  if (!is_null) {
84  is_nullable_ = false;
85  }
86  return std::make_tuple(std::vector<llvm::Value*>{array_buff_ptr}, is_null);
87  }
88 
89  std::vector<llvm::Value*> codegen(const std::vector<llvm::Value*>& args,
90  CodeGenerator::NullCheckCodegen* nullcheck_codegen,
91  CgenState* cgen_state,
92  const CompilationOptions& co) final {
93  CHECK_EQ(args.size(), size_t(1));
94  const auto array_buff_ptr = args.front();
95 
96  const auto& geo_ti = getOperand(0)->get_type_info();
97  CHECK(geo_ti.is_geometry());
98  auto& builder = cgen_state->ir_builder_;
99 
100  const bool is_x = operator_->getName() == "ST_X";
101  const std::string expr_name = is_x ? "x" : "y";
102 
103  llvm::Value* coord_lv;
104  if (geo_ti.get_compression() == kENCODING_GEOINT) {
105  auto compressed_arr_ptr = builder.CreateBitCast(
106  array_buff_ptr, llvm::Type::getInt32PtrTy(cgen_state->context_));
107  auto coord_index = is_x ? cgen_state->llInt(0) : cgen_state->llInt(1);
108  auto coord_lv_ptr = builder.CreateGEP(
109  compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
110  compressed_arr_ptr,
111  coord_index,
112  expr_name + "_coord_ptr");
113  auto compressed_coord_lv =
114  builder.CreateLoad(coord_lv_ptr->getType()->getPointerElementType(),
115  coord_lv_ptr,
116  expr_name + "_coord_compressed");
117 
118  coord_lv =
119  cgen_state->emitExternalCall("decompress_" + expr_name + "_coord_geoint",
120  llvm::Type::getDoubleTy(cgen_state->context_),
121  {compressed_coord_lv});
122  } else {
123  auto coord_arr_ptr = builder.CreateBitCast(
124  array_buff_ptr, llvm::Type::getDoublePtrTy(cgen_state->context_));
125  auto coord_index = is_x ? cgen_state->llInt(0) : cgen_state->llInt(1);
126  auto coord_lv_ptr = builder.CreateGEP(
127  coord_arr_ptr->getType()->getScalarType()->getPointerElementType(),
128  coord_arr_ptr,
129  coord_index,
130  expr_name + "_coord_ptr");
131  coord_lv = builder.CreateLoad(coord_lv_ptr->getType()->getPointerElementType(),
132  coord_lv_ptr,
133  expr_name + "_coord");
134  }
135 
136  auto ret = coord_lv;
137  if (is_nullable_) {
138  CHECK(nullcheck_codegen);
139  ret = nullcheck_codegen->finalize(cgen_state->inlineFpNull(SQLTypeInfo(kDOUBLE)),
140  ret);
141  }
142  const auto key = operator_->toString();
143  CHECK(cgen_state->geo_target_cache_.insert(std::make_pair(key, ret)).second);
144  return {ret};
145  }
146 };
147 
148 } // namespace spatial_type
#define CHECK_EQ(x, y)
Definition: Logger.h:301
PointAccessors(const Analyzer::GeoOperator *geo_operator)
size_t size() const final
llvm::Value * codegenCmpEqNullptr(llvm::IRBuilder<> &builder, llvm::Value *arg_lv)
llvm::Value * buffer
Definition: CgenState.h:36
static char const * pointIsNullFunctionName(SQLTypeInfo const &)
Definition: Codegen.cpp:69
CONSTEXPR DEVICE bool is_null(const T &value)
const std::string & getName() const
Definition: Analyzer.h:3298
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
SQLTypeInfo getNullType() const final
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
static ArrayLoadCodegen codegenGeoArrayLoadAndNullcheck(llvm::Value *byte_stream, llvm::Value *pos, const SQLTypeInfo &ti, CgenState *cgen_state)
Definition: GeoIR.cpp:25
const Analyzer::GeoOperator * operator_
Definition: Codegen.h:69
size_t size() const
Definition: Analyzer.cpp:4211
std::vector< llvm::Value * > codegen(const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) final
#define CHECK(condition)
Definition: Logger.h:291
virtual const Analyzer::Expr * getOperand(const size_t index)
Definition: Codegen.cpp:64
std::string toString() const override
Definition: Analyzer.cpp:4183