OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
spatial_type::Transform Class Reference

#include <Transform.h>

+ Inheritance diagram for spatial_type::Transform:
+ Collaboration diagram for spatial_type::Transform:

Public Member Functions

 Transform (const Analyzer::GeoOperator *geo_operator)
 
size_t size () const override
 
SQLTypeInfo getNullType () const override
 
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) override
 
std::vector< llvm::Value * > codegen (const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) override
 
- Public Member Functions inherited from spatial_type::Codegen
 Codegen (const Analyzer::GeoOperator *geo_operator)
 
auto isNullable () const
 
auto getTypeInfo () const
 
std::string getName () const
 
virtual std::unique_ptr
< CodeGenerator::NullCheckCodegen
getNullCheckCodegen (llvm::Value *null_lv, CgenState *cgen_state, Executor *executor)
 
virtual const Analyzer::ExprgetOperand (const size_t index)
 
virtual ~Codegen ()
 

Static Public Member Functions

static bool isUtm (unsigned const srid)
 
- Static Public Member Functions inherited from spatial_type::Codegen
static std::unique_ptr< Codegeninit (const Analyzer::GeoOperator *geo_operator)
 

Private Attributes

const
Analyzer::GeoTransformOperator
transform_operator_
 
bool can_transform_in_place_ {false}
 

Additional Inherited Members

- Protected Attributes inherited from spatial_type::Codegen
const Analyzer::GeoOperatoroperator_
 
bool is_nullable_ {true}
 

Detailed Description

Definition at line 22 of file Transform.h.

Constructor & Destructor Documentation

spatial_type::Transform::Transform ( const Analyzer::GeoOperator geo_operator)
inline

Definition at line 24 of file Transform.h.

References CHECK, CHECK_EQ, Analyzer::Expr::get_type_info(), spatial_type::Codegen::is_nullable_, spatial_type::Codegen::operator_, Analyzer::GeoOperator::size(), and transform_operator_.

25  : Codegen(geo_operator)
27  dynamic_cast<const Analyzer::GeoTransformOperator*>(geo_operator)) {
28  CHECK_EQ(operator_->size(), size_t(1)); // geo input expr
30  const auto& ti = geo_operator->get_type_info();
31  if (ti.get_notnull()) {
32  is_nullable_ = false;
33  } else {
34  is_nullable_ = true;
35  }
36  }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
const Analyzer::GeoOperator * operator_
Definition: Codegen.h:67
size_t size() const
Definition: Analyzer.cpp:4182
const Analyzer::GeoTransformOperator * transform_operator_
Definition: Transform.h:286
#define CHECK(condition)
Definition: Logger.h:291
Codegen(const Analyzer::GeoOperator *geo_operator)
Definition: Codegen.h:28

+ Here is the call graph for this function:

Member Function Documentation

std::vector<llvm::Value*> spatial_type::Transform::codegen ( const std::vector< llvm::Value * > &  args,
CodeGenerator::NullCheckCodegen nullcheck_codegen,
CgenState cgen_state,
const CompilationOptions co 
)
inlineoverridevirtual

Implements spatial_type::Codegen.

Definition at line 88 of file Transform.h.

References can_transform_in_place_, CHECK, CHECK_EQ, CgenState::context_, CompilationOptions::device_type, CgenState::emitCall(), CgenState::emitExternalCall(), CodeGenerator::NullCheckCodegen::finalize(), Analyzer::Expr::get_type_info(), Analyzer::GeoTransformOperator::getInputSRID(), spatial_type::Codegen::getName(), spatial_type::Codegen::getOperand(), Analyzer::GeoTransformOperator::getOutputSRID(), GPU, CgenState::gpuFunctionsToReplace(), CgenState::ir_builder_, spatial_type::Codegen::is_nullable_, isUtm(), kENCODING_GEOINT, CgenState::llInt(), CgenState::maybeCloneFunctionRecursive(), CgenState::module_, CgenState::replaceFunctionForGpu(), to_string(), transform_operator_, and verify_function_ir().

91  {
92  CHECK_EQ(args.size(), size_t(1));
93 
94  const auto geo_operand = getOperand(0);
95  const auto& operand_ti = geo_operand->get_type_info();
96  auto& builder = cgen_state->ir_builder_;
97 
98  llvm::Value* arr_buff_ptr = args.front();
99  if (operand_ti.get_compression() == kENCODING_GEOINT) {
100  // decompress
101  auto new_arr_ptr =
102  builder.CreateAlloca(llvm::Type::getDoubleTy(cgen_state->context_),
103  cgen_state->llInt(int32_t(2)),
104  getName() + "_Array");
105  auto compressed_arr_ptr = builder.CreateBitCast(
106  arr_buff_ptr, llvm::Type::getInt32PtrTy(cgen_state->context_));
107  // x coord
108  auto* gep = builder.CreateGEP(
109  compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
110  compressed_arr_ptr,
111  cgen_state->llInt(0));
112  auto x_coord_lv = cgen_state->emitExternalCall(
113  "decompress_x_coord_geoint",
114  llvm::Type::getDoubleTy(cgen_state->context_),
115  {builder.CreateLoad(
116  gep->getType()->getPointerElementType(), gep, "compressed_x_coord")});
117  builder.CreateStore(
118  x_coord_lv,
119  builder.CreateGEP(
120  new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
121  new_arr_ptr,
122  cgen_state->llInt(0)));
123  gep = builder.CreateGEP(
124  compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
125  compressed_arr_ptr,
126  cgen_state->llInt(1));
127  auto y_coord_lv = cgen_state->emitExternalCall(
128  "decompress_y_coord_geoint",
129  llvm::Type::getDoubleTy(cgen_state->context_),
130  {builder.CreateLoad(
131  gep->getType()->getPointerElementType(), gep, "compressed_y_coord")});
132  builder.CreateStore(
133  y_coord_lv,
134  builder.CreateGEP(
135  new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
136  new_arr_ptr,
137  cgen_state->llInt(1)));
138  arr_buff_ptr = new_arr_ptr;
139  } else if (!can_transform_in_place_) {
140  auto new_arr_ptr =
141  builder.CreateAlloca(llvm::Type::getDoubleTy(cgen_state->context_),
142  cgen_state->llInt(int32_t(2)),
143  getName() + "_Array");
144  const auto arr_buff_ptr_cast = builder.CreateBitCast(
145  arr_buff_ptr, llvm::Type::getDoublePtrTy(cgen_state->context_));
146 
147  auto* gep = builder.CreateGEP(
148  arr_buff_ptr_cast->getType()->getScalarType()->getPointerElementType(),
149  arr_buff_ptr_cast,
150  cgen_state->llInt(0));
151  builder.CreateStore(
152  builder.CreateLoad(gep->getType()->getPointerElementType(), gep),
153  builder.CreateGEP(
154  new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
155  new_arr_ptr,
156  cgen_state->llInt(0)));
157  gep = builder.CreateGEP(
158  arr_buff_ptr_cast->getType()->getScalarType()->getPointerElementType(),
159  arr_buff_ptr_cast,
160  cgen_state->llInt(1));
161  builder.CreateStore(
162  builder.CreateLoad(gep->getType()->getPointerElementType(), gep),
163  builder.CreateGEP(
164  new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
165  new_arr_ptr,
166  cgen_state->llInt(1)));
167  arr_buff_ptr = new_arr_ptr;
168  }
169  CHECK(arr_buff_ptr->getType() == llvm::Type::getDoublePtrTy(cgen_state->context_));
170 
171  auto const srid_in = static_cast<unsigned>(transform_operator_->getInputSRID());
172  auto const srid_out = static_cast<unsigned>(transform_operator_->getOutputSRID());
173  if (srid_in == srid_out) {
174  // noop
175  return {args.front()};
176  }
177 
178  // transform in place
179  std::string transform_function_prefix{""};
180  std::vector<llvm::Value*> transform_args;
181 
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));
188  } else {
189  throw std::runtime_error("Unsupported input SRID " + std::to_string(srid_in) +
190  " for output SRID " + std::to_string(srid_out));
191  }
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));
198  } else {
199  throw std::runtime_error("Unsupported input SRID " + std::to_string(srid_in) +
200  " for output SRID " + std::to_string(srid_out));
201  }
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_";
207  } else {
208  throw std::runtime_error("Unsupported input SRID " + std::to_string(srid_in) +
209  " for output SRID " + std::to_string(srid_out));
210  }
211  transform_args.push_back(cgen_state->llInt(srid_out));
212  } else {
213  throw std::runtime_error("Unsupported output SRID for ST_Transform: " +
214  std::to_string(srid_out));
215  }
216  CHECK(!transform_function_prefix.empty());
217 
218  auto x_coord_ptr_lv = builder.CreateGEP(
219  arr_buff_ptr->getType()->getScalarType()->getPointerElementType(),
220  arr_buff_ptr,
221  cgen_state->llInt(0),
222  "x_coord_ptr");
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(),
227  arr_buff_ptr,
228  cgen_state->llInt(1),
229  "y_coord_ptr");
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');
234  CHECK(fn_x);
235  cgen_state->maybeCloneFunctionRecursive(fn_x);
236  CHECK(!fn_x->isDeclaration());
237 
238  auto gpu_functions_to_replace = cgen_state->gpuFunctionsToReplace(fn_x);
239  for (const auto& fcn_name : gpu_functions_to_replace) {
240  cgen_state->replaceFunctionForGpu(fcn_name, fn_x);
241  }
242  verify_function_ir(fn_x);
243  auto transform_call = builder.CreateCall(fn_x, transform_args);
244  builder.CreateStore(transform_call, x_coord_ptr_lv);
245 
246  auto fn_y = cgen_state->module_->getFunction(transform_function_prefix + 'y');
247  CHECK(fn_y);
248  cgen_state->maybeCloneFunctionRecursive(fn_y);
249  CHECK(!fn_y->isDeclaration());
250 
251  gpu_functions_to_replace = cgen_state->gpuFunctionsToReplace(fn_y);
252  for (const auto& fcn_name : gpu_functions_to_replace) {
253  cgen_state->replaceFunctionForGpu(fcn_name, fn_y);
254  }
255  verify_function_ir(fn_y);
256  transform_call = builder.CreateCall(fn_y, transform_args);
257  builder.CreateStore(transform_call, y_coord_ptr_lv);
258  } else {
259  builder.CreateStore(
260  cgen_state->emitCall(transform_function_prefix + 'x', transform_args),
261  x_coord_ptr_lv);
262  builder.CreateStore(
263  cgen_state->emitCall(transform_function_prefix + 'y', transform_args),
264  y_coord_ptr_lv);
265  }
266  auto ret = arr_buff_ptr;
267  const auto& geo_ti = transform_operator_->get_type_info();
268 
269  if (is_nullable_) {
270  CHECK(nullcheck_codegen);
271  ret = nullcheck_codegen->finalize(
272  llvm::ConstantPointerNull::get(
273  geo_ti.get_compression() == kENCODING_GEOINT
274  ? llvm::PointerType::get(llvm::Type::getInt32Ty(cgen_state->context_),
275  0)
276  : llvm::PointerType::get(llvm::Type::getDoubleTy(cgen_state->context_),
277  0)),
278  ret);
279  }
280  return {ret,
281  cgen_state->llInt(static_cast<int32_t>(
282  geo_ti.get_compression() == kENCODING_GEOINT ? 8 : 16))};
283  }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
int32_t getInputSRID() const
Definition: Analyzer.h:3207
void maybeCloneFunctionRecursive(llvm::Function *fn)
Definition: CgenState.cpp:181
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
std::string to_string(char const *&&v)
llvm::Module * module_
Definition: CgenState.h:373
void verify_function_ir(const llvm::Function *func)
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
void replaceFunctionForGpu(const std::string &fcn_to_replace, llvm::Function *fn)
Definition: CgenState.cpp:329
std::vector< std::string > gpuFunctionsToReplace(llvm::Function *fn)
Definition: CgenState.cpp:306
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
int32_t getOutputSRID() const
Definition: Analyzer.h:3209
ExecutorDeviceType device_type
static bool isUtm(unsigned const srid)
Definition: Transform.h:42
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
const Analyzer::GeoTransformOperator * transform_operator_
Definition: Transform.h:286
llvm::Value * finalize(llvm::Value *null_lv, llvm::Value *notnull_lv)
Definition: IRCodegen.cpp:1529
#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

+ Here is the call graph for this function:

std::tuple<std::vector<llvm::Value*>, llvm::Value*> spatial_type::Transform::codegenLoads ( const std::vector< llvm::Value * > &  arg_lvs,
const std::vector< llvm::Value * > &  pos_lvs,
CgenState cgen_state 
)
inlineoverridevirtual

Implements spatial_type::Codegen.

Definition at line 46 of file Transform.h.

References can_transform_in_place_, CHECK, CHECK_EQ, CodeGenerator::codegenGeoArrayLoadAndNullcheck(), CgenState::context_, spatial_type::Codegen::getOperand(), CgenState::ir_builder_, is_null(), spatial_type::Codegen::is_nullable_, kENCODING_GEOINT, kPOINT, size(), and UNREACHABLE.

49  {
50  CHECK_EQ(pos_lvs.size(), size());
51  const auto geo_operand = getOperand(0);
52  const auto& operand_ti = geo_operand->get_type_info();
53  CHECK(operand_ti.is_geometry() && operand_ti.get_type() == kPOINT);
54 
55  if (dynamic_cast<const Analyzer::ColumnVar*>(geo_operand)) {
56  CHECK_EQ(arg_lvs.size(), size_t(1)); // col_byte_stream
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)) {
62  CHECK_EQ(arg_lvs.size(), size_t(2)); // ptr, size
63 
64  // nulls not supported, and likely compressed, so require a new buffer for the
65  // transformation
67  return std::make_tuple(std::vector<llvm::Value*>{arg_lvs.front()}, nullptr);
68  } else {
69  CHECK(arg_lvs.size() == size_t(1) ||
70  arg_lvs.size() == size_t(2)); // ptr or ptr, size
71  // coming from a temporary, can modify the memory pointer directly
73  auto& builder = cgen_state->ir_builder_;
74 
75  const auto is_null = builder.CreateICmp(
76  llvm::CmpInst::ICMP_EQ,
77  arg_lvs.front(),
78  llvm::ConstantPointerNull::get( // TODO: check ptr address space
79  operand_ti.get_compression() == kENCODING_GEOINT
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);
83  }
84  UNREACHABLE();
85  return std::make_tuple(std::vector<llvm::Value*>{}, nullptr);
86  }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
#define UNREACHABLE()
Definition: Logger.h:338
llvm::LLVMContext & context_
Definition: CgenState.h:382
CONSTEXPR DEVICE bool is_null(const T &value)
size_t size() const override
Definition: Transform.h:38
static ArrayLoadCodegen codegenGeoArrayLoadAndNullcheck(llvm::Value *byte_stream, llvm::Value *pos, const SQLTypeInfo &ti, CgenState *cgen_state)
Definition: GeoIR.cpp:23
#define CHECK(condition)
Definition: Logger.h:291
virtual const Analyzer::Expr * getOperand(const size_t index)
Definition: Codegen.cpp:64

+ Here is the call graph for this function:

SQLTypeInfo spatial_type::Transform::getNullType ( ) const
inlineoverridevirtual

Implements spatial_type::Codegen.

Definition at line 40 of file Transform.h.

References kBOOLEAN.

40 { return SQLTypeInfo(kBOOLEAN); }
static bool spatial_type::Transform::isUtm ( unsigned const  srid)
inlinestatic

Definition at line 42 of file Transform.h.

Referenced by codegen(), and RelAlgTranslator::translateGeoFunctionArg().

42  {
43  return (32601 <= srid && srid <= 32660) || (32701 <= srid && srid <= 32760);
44  }

+ Here is the caller graph for this function:

size_t spatial_type::Transform::size ( ) const
inlineoverridevirtual

Implements spatial_type::Codegen.

Definition at line 38 of file Transform.h.

Referenced by codegenLoads().

38 { return 1; }

+ Here is the caller graph for this function:

Member Data Documentation

bool spatial_type::Transform::can_transform_in_place_ {false}
private

Definition at line 287 of file Transform.h.

Referenced by codegen(), and codegenLoads().

const Analyzer::GeoTransformOperator* spatial_type::Transform::transform_operator_
private

Definition at line 286 of file Transform.h.

Referenced by codegen(), and Transform().


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