19 namespace spatial_type {
27 dynamic_cast<const Analyzer::GeoTransformOperator*>(geo_operator)) {
31 if (ti.get_notnull()) {
38 size_t size()
const override {
return 1; }
42 inline static bool isUtm(
unsigned const srid) {
43 return (32601 <= srid && srid <= 32660) || (32701 <= srid && srid <= 32760);
47 const std::vector<llvm::Value*>& arg_lvs,
48 const std::vector<llvm::Value*>& pos_lvs,
52 const auto& operand_ti = geo_operand->get_type_info();
53 CHECK(operand_ti.is_geometry() && operand_ti.get_type() ==
kPOINT);
55 if (dynamic_cast<const Analyzer::ColumnVar*>(geo_operand)) {
58 arg_lvs.front(), pos_lvs.front(), operand_ti, cgen_state);
59 return std::make_tuple(std::vector<llvm::Value*>{arr_load_lvs.buffer},
60 arr_load_lvs.is_null);
61 }
else if (dynamic_cast<const Analyzer::GeoConstant*>(geo_operand)) {
67 return std::make_tuple(std::vector<llvm::Value*>{arg_lvs.front()},
nullptr);
69 CHECK(arg_lvs.size() == size_t(1) ||
70 arg_lvs.size() == size_t(2));
75 const auto is_null = builder.CreateICmp(
76 llvm::CmpInst::ICMP_EQ,
78 llvm::ConstantPointerNull::get(
80 ? llvm::Type::getInt32PtrTy(cgen_state->
context_)
81 : llvm::Type::getDoublePtrTy(cgen_state->
context_)));
82 return std::make_tuple(std::vector<llvm::Value*>{arg_lvs.front()},
is_null);
85 return std::make_tuple(std::vector<llvm::Value*>{},
nullptr);
88 std::vector<llvm::Value*>
codegen(
const std::vector<llvm::Value*>&
args,
95 const auto& operand_ti = geo_operand->get_type_info();
98 llvm::Value* arr_buff_ptr = args.front();
102 builder.CreateAlloca(llvm::Type::getDoubleTy(cgen_state->
context_),
103 cgen_state->
llInt(int32_t(2)),
105 auto compressed_arr_ptr = builder.CreateBitCast(
106 arr_buff_ptr, llvm::Type::getInt32PtrTy(cgen_state->
context_));
108 auto* gep = builder.CreateGEP(
109 compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
111 cgen_state->
llInt(0));
113 "decompress_x_coord_geoint",
114 llvm::Type::getDoubleTy(cgen_state->
context_),
116 gep->getType()->getPointerElementType(), gep,
"compressed_x_coord")});
120 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
122 cgen_state->
llInt(0)));
123 gep = builder.CreateGEP(
124 compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
126 cgen_state->
llInt(1));
128 "decompress_y_coord_geoint",
129 llvm::Type::getDoubleTy(cgen_state->
context_),
131 gep->getType()->getPointerElementType(), gep,
"compressed_y_coord")});
135 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
137 cgen_state->
llInt(1)));
138 arr_buff_ptr = new_arr_ptr;
141 builder.CreateAlloca(llvm::Type::getDoubleTy(cgen_state->
context_),
142 cgen_state->
llInt(int32_t(2)),
144 const auto arr_buff_ptr_cast = builder.CreateBitCast(
145 arr_buff_ptr, llvm::Type::getDoublePtrTy(cgen_state->
context_));
147 auto* gep = builder.CreateGEP(
148 arr_buff_ptr_cast->getType()->getScalarType()->getPointerElementType(),
150 cgen_state->
llInt(0));
152 builder.CreateLoad(gep->getType()->getPointerElementType(), gep),
154 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
156 cgen_state->
llInt(0)));
157 gep = builder.CreateGEP(
158 arr_buff_ptr_cast->getType()->getScalarType()->getPointerElementType(),
160 cgen_state->
llInt(1));
162 builder.CreateLoad(gep->getType()->getPointerElementType(), gep),
164 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
166 cgen_state->
llInt(1)));
167 arr_buff_ptr = new_arr_ptr;
169 CHECK(arr_buff_ptr->getType() == llvm::Type::getDoublePtrTy(cgen_state->
context_));
173 if (srid_in == srid_out) {
175 return {args.front()};
179 std::string transform_function_prefix{
""};
180 std::vector<llvm::Value*> transform_args;
182 if (srid_out == 900913) {
183 if (srid_in == 4326) {
184 transform_function_prefix =
"transform_4326_900913_";
185 }
else if (
isUtm(srid_in)) {
186 transform_function_prefix =
"transform_utm_900913_";
187 transform_args.push_back(cgen_state->
llInt(srid_in));
189 throw std::runtime_error(
"Unsupported input SRID " +
std::to_string(srid_in) +
192 }
else if (srid_out == 4326) {
193 if (srid_in == 900913) {
194 transform_function_prefix =
"transform_900913_4326_";
195 }
else if (
isUtm(srid_in)) {
196 transform_function_prefix =
"transform_utm_4326_";
197 transform_args.push_back(cgen_state->
llInt(srid_in));
199 throw std::runtime_error(
"Unsupported input SRID " +
std::to_string(srid_in) +
202 }
else if (
isUtm(srid_out)) {
203 if (srid_in == 4326) {
204 transform_function_prefix =
"transform_4326_utm_";
205 }
else if (srid_in == 900913) {
206 transform_function_prefix =
"transform_900913_utm_";
208 throw std::runtime_error(
"Unsupported input SRID " +
std::to_string(srid_in) +
211 transform_args.push_back(cgen_state->
llInt(srid_out));
213 throw std::runtime_error(
"Unsupported output SRID for ST_Transform: " +
216 CHECK(!transform_function_prefix.empty());
218 auto x_coord_ptr_lv = builder.CreateGEP(
219 arr_buff_ptr->getType()->getScalarType()->getPointerElementType(),
221 cgen_state->
llInt(0),
223 transform_args.push_back(builder.CreateLoad(
224 x_coord_ptr_lv->getType()->getPointerElementType(), x_coord_ptr_lv,
"x_coord"));
225 auto y_coord_ptr_lv = builder.CreateGEP(
226 arr_buff_ptr->getType()->getScalarType()->getPointerElementType(),
228 cgen_state->
llInt(1),
230 transform_args.push_back(builder.CreateLoad(
231 y_coord_ptr_lv->getType()->getPointerElementType(), y_coord_ptr_lv,
"y_coord"));
233 auto fn_x = cgen_state->
module_->getFunction(transform_function_prefix +
'x');
236 CHECK(!fn_x->isDeclaration());
239 for (
const auto& fcn_name : gpu_functions_to_replace) {
243 auto transform_call = builder.CreateCall(fn_x, transform_args);
244 builder.CreateStore(transform_call, x_coord_ptr_lv);
246 auto fn_y = cgen_state->
module_->getFunction(transform_function_prefix +
'y');
249 CHECK(!fn_y->isDeclaration());
252 for (
const auto& fcn_name : gpu_functions_to_replace) {
256 transform_call = builder.CreateCall(fn_y, transform_args);
257 builder.CreateStore(transform_call, y_coord_ptr_lv);
260 cgen_state->
emitCall(transform_function_prefix +
'x', transform_args),
263 cgen_state->
emitCall(transform_function_prefix +
'y', transform_args),
266 auto ret = arr_buff_ptr;
270 CHECK(nullcheck_codegen);
272 llvm::ConstantPointerNull::get(
274 ? llvm::PointerType::get(llvm::Type::getInt32Ty(cgen_state->
context_),
276 : llvm::PointerType::get(llvm::Type::getDoubleTy(cgen_state->
context_),
281 cgen_state->
llInt(static_cast<int32_t>(
void maybeCloneFunctionRecursive(llvm::Function *fn)
llvm::IRBuilder ir_builder_
void verify_function_ir(const llvm::Function *func)
llvm::LLVMContext & context_
CONSTEXPR DEVICE bool is_null(const T &value)
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)
void replaceFunctionForGpu(const std::string &fcn_to_replace, llvm::Function *fn)
std::vector< std::string > gpuFunctionsToReplace(llvm::Function *fn)
const SQLTypeInfo & get_type_info() const
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
ExecutorDeviceType device_type
static ArrayLoadCodegen codegenGeoArrayLoadAndNullcheck(llvm::Value *byte_stream, llvm::Value *pos, const SQLTypeInfo &ti, CgenState *cgen_state)
const Analyzer::GeoOperator * operator_
llvm::ConstantInt * llInt(const T v) const
llvm::Value * finalize(llvm::Value *null_lv, llvm::Value *notnull_lv)
virtual const Analyzer::Expr * getOperand(const size_t index)
std::string getName() const