OmniSciDB  0264ff685a
ConstantIR.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, 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 #include "CodeGenerator.h"
18 #include "Execute.h"
19 
20 std::vector<llvm::Value*> CodeGenerator::codegen(const Analyzer::Constant* constant,
21  const EncodingType enc_type,
22  const int dict_id,
23  const CompilationOptions& co) {
25  if (co.hoist_literals) {
26  std::vector<const Analyzer::Constant*> constants(
27  executor()->deviceCount(co.device_type), constant);
28  return codegenHoistedConstants(constants, enc_type, dict_id);
29  }
30  const auto& type_info = constant->get_type_info();
31  const auto type =
32  type_info.is_decimal() ? decimal_to_int_type(type_info) : type_info.get_type();
33  switch (type) {
34  case kBOOLEAN:
35  return {llvm::ConstantInt::get(get_int_type(8, cgen_state_->context_),
36  constant->get_constval().boolval)};
37  case kTINYINT:
38  case kSMALLINT:
39  case kINT:
40  case kBIGINT:
41  case kTIME:
42  case kTIMESTAMP:
43  case kDATE:
44  case kINTERVAL_DAY_TIME:
46  return {CodeGenerator::codegenIntConst(constant, cgen_state_)};
47  case kFLOAT:
48  return {llvm::ConstantFP::get(llvm::Type::getFloatTy(cgen_state_->context_),
49  constant->get_constval().floatval)};
50  case kDOUBLE:
51  return {llvm::ConstantFP::get(llvm::Type::getDoubleTy(cgen_state_->context_),
52  constant->get_constval().doubleval)};
53  case kVARCHAR:
54  case kCHAR:
55  case kTEXT: {
56  CHECK(constant->get_constval().stringval || constant->get_is_null());
57  if (constant->get_is_null()) {
58  if (enc_type == kENCODING_DICT) {
59  return {
60  cgen_state_->llInt(static_cast<int32_t>(inline_int_null_val(type_info)))};
61  }
62  return {cgen_state_->llInt(int64_t(0)),
63  llvm::Constant::getNullValue(
64  llvm::PointerType::get(get_int_type(8, cgen_state_->context_), 0)),
65  cgen_state_->llInt(int32_t(0))};
66  }
67  const auto& str_const = *constant->get_constval().stringval;
68  if (enc_type == kENCODING_DICT) {
69  return {
71  ->getStringDictionaryProxy(
72  dict_id, executor()->getRowSetMemoryOwner(), true)
73  ->getIdOfString(str_const))};
74  }
75  return {cgen_state_->llInt(int64_t(0)),
76  cgen_state_->addStringConstant(str_const),
77  cgen_state_->llInt(static_cast<int32_t>(str_const.size()))};
78  }
79  default:
80  CHECK(false);
81  }
82  abort();
83 }
84 
85 llvm::ConstantInt* CodeGenerator::codegenIntConst(const Analyzer::Constant* constant,
86  CgenState* cgen_state) {
87  const auto& type_info = constant->get_type_info();
88  if (constant->get_is_null()) {
89  return cgen_state->inlineIntNull(type_info);
90  }
91  const auto type =
92  type_info.is_decimal() ? decimal_to_int_type(type_info) : type_info.get_type();
93  switch (type) {
94  case kTINYINT:
95  return cgen_state->llInt(constant->get_constval().tinyintval);
96  case kSMALLINT:
97  return cgen_state->llInt(constant->get_constval().smallintval);
98  case kINT:
99  return cgen_state->llInt(constant->get_constval().intval);
100  case kBIGINT:
101  return cgen_state->llInt(constant->get_constval().bigintval);
102  case kTIME:
103  case kTIMESTAMP:
104  case kDATE:
105  case kINTERVAL_DAY_TIME:
107  return cgen_state->llInt(constant->get_constval().bigintval);
108  default:
109  UNREACHABLE();
110  }
111  UNREACHABLE();
112  return nullptr;
113 }
114 
116  const SQLTypeInfo& type_info,
117  const EncodingType enc_type,
118  const int dict_id,
119  const int16_t lit_off) {
121  std::string literal_name = "literal_" + std::to_string(lit_off);
122  auto lit_buff_query_func_lv = get_arg_by_name(cgen_state_->query_func_, "literals");
123  const auto lit_buf_start = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
124  lit_buff_query_func_lv, cgen_state_->llInt(lit_off));
125  if (type_info.is_string() && enc_type != kENCODING_DICT) {
127  CHECK_EQ(size_t(4),
129  auto off_and_len_ptr = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(
130  lit_buf_start,
131  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0));
132  // packed offset + length, 16 bits each
133  auto off_and_len =
134  cgen_state_->query_func_entry_ir_builder_.CreateLoad(off_and_len_ptr);
135  auto off_lv = cgen_state_->query_func_entry_ir_builder_.CreateLShr(
137  off_and_len, cgen_state_->llInt(int32_t(0xffff0000))),
138  cgen_state_->llInt(int32_t(16)));
139  auto len_lv = cgen_state_->query_func_entry_ir_builder_.CreateAnd(
140  off_and_len, cgen_state_->llInt(int32_t(0x0000ffff)));
141 
142  auto var_start = cgen_state_->llInt(int64_t(0));
143  auto var_start_address = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
144  lit_buff_query_func_lv, off_lv);
145  auto var_length = len_lv;
146 
147  var_start->setName(literal_name + "_start");
148  var_start_address->setName(literal_name + "_start_address");
149  var_length->setName(literal_name + "_length");
150 
151  return {var_start, var_start_address, var_length};
152  } else if (type_info.is_array() &&
153  (enc_type == kENCODING_NONE || enc_type == kENCODING_GEOINT)) {
154  if (enc_type == kENCODING_NONE) {
156  } else if (enc_type == kENCODING_GEOINT) {
158  CHECK_EQ(kTINYINT, type_info.get_subtype());
159  }
160 
161  auto off_and_len_ptr = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(
162  lit_buf_start,
163  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0));
164  // packed offset + length, 16 bits each
165  auto off_and_len =
166  cgen_state_->query_func_entry_ir_builder_.CreateLoad(off_and_len_ptr);
167  auto off_lv = cgen_state_->query_func_entry_ir_builder_.CreateLShr(
169  off_and_len, cgen_state_->llInt(int32_t(0xffff0000))),
170  cgen_state_->llInt(int32_t(16)));
171  auto len_lv = cgen_state_->query_func_entry_ir_builder_.CreateAnd(
172  off_and_len, cgen_state_->llInt(int32_t(0x0000ffff)));
173 
174  auto var_start_address = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
175  lit_buff_query_func_lv, off_lv);
176  auto var_length = len_lv;
177 
178  var_start_address->setName(literal_name + "_start_address");
179  var_length->setName(literal_name + "_length");
180 
181  return {var_start_address, var_length};
182  }
183 
184  llvm::Type* val_ptr_type{nullptr};
185  const auto val_bits = get_bit_width(type_info);
186  CHECK_EQ(size_t(0), val_bits % 8);
187  if (type_info.is_integer() || type_info.is_decimal() || type_info.is_time() ||
188  type_info.is_timeinterval() || type_info.is_string() || type_info.is_boolean()) {
189  val_ptr_type = llvm::PointerType::get(
190  llvm::IntegerType::get(cgen_state_->context_, val_bits), 0);
191  } else {
192  CHECK(type_info.get_type() == kFLOAT || type_info.get_type() == kDOUBLE);
193  val_ptr_type = (type_info.get_type() == kFLOAT)
194  ? llvm::Type::getFloatPtrTy(cgen_state_->context_)
195  : llvm::Type::getDoublePtrTy(cgen_state_->context_);
196  }
197  auto lit_lv = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
198  cgen_state_->query_func_entry_ir_builder_.CreateBitCast(lit_buf_start,
199  val_ptr_type));
200  lit_lv->setName(literal_name);
201  return {lit_lv};
202 }
203 
205  const SQLTypeInfo& type_info,
206  const EncodingType enc_type,
207  const int16_t lit_off,
208  const std::vector<llvm::Value*>& literal_loads) {
210  std::string literal_name = "literal_" + std::to_string(lit_off);
211 
212  if (type_info.is_string() && enc_type != kENCODING_DICT) {
213  CHECK_EQ(literal_loads.size(), 3u);
214 
215  llvm::Value* var_start = literal_loads[0];
216  llvm::Value* var_start_address = literal_loads[1];
217  llvm::Value* var_length = literal_loads[2];
218 
219  llvm::PointerType* placeholder0_type =
220  llvm::PointerType::get(var_start->getType(), 0);
221  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
222  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder0_type),
223  "__placeholder__" + literal_name + "_start");
224  llvm::PointerType* placeholder1_type =
225  llvm::PointerType::get(var_start_address->getType(), 0);
226  auto placeholder1 = cgen_state_->ir_builder_.CreateLoad(
227  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder1_type),
228  "__placeholder__" + literal_name + "_start_address");
229  llvm::PointerType* placeholder2_type =
230  llvm::PointerType::get(var_length->getType(), 0);
231  auto placeholder2 = cgen_state_->ir_builder_.CreateLoad(
232  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder2_type),
233  "__placeholder__" + literal_name + "_length");
234 
235  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
236  cgen_state_->row_func_hoisted_literals_[placeholder1] = {lit_off, 1};
237  cgen_state_->row_func_hoisted_literals_[placeholder2] = {lit_off, 2};
238 
239  return {placeholder0, placeholder1, placeholder2};
240  }
241 
242  if (type_info.is_array() &&
243  (enc_type == kENCODING_NONE || enc_type == kENCODING_GEOINT)) {
244  CHECK_EQ(literal_loads.size(), 2u);
245 
246  llvm::Value* var_start_address = literal_loads[0];
247  llvm::Value* var_length = literal_loads[1];
248 
249  llvm::PointerType* placeholder0_type =
250  llvm::PointerType::get(var_start_address->getType(), 0);
251  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
252  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder0_type),
253  "__placeholder__" + literal_name + "_start_address");
254  llvm::PointerType* placeholder1_type =
255  llvm::PointerType::get(var_length->getType(), 0);
256  auto placeholder1 = cgen_state_->ir_builder_.CreateLoad(
257  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder1_type),
258  "__placeholder__" + literal_name + "_length");
259 
260  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
261  cgen_state_->row_func_hoisted_literals_[placeholder1] = {lit_off, 1};
262 
263  return {placeholder0, placeholder1};
264  }
265 
266  CHECK_EQ(literal_loads.size(), 1u);
267  llvm::Value* to_return_lv = literal_loads[0];
268 
269  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
270  cgen_state_->ir_builder_.CreateIntToPtr(
271  cgen_state_->llInt(0), llvm::PointerType::get(to_return_lv->getType(), 0)),
272  "__placeholder__" + literal_name);
273 
274  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
275 
276  return {placeholder0};
277 }
278 
279 std::vector<llvm::Value*> CodeGenerator::codegenHoistedConstants(
280  const std::vector<const Analyzer::Constant*>& constants,
281  const EncodingType enc_type,
282  const int dict_id) {
284  CHECK(!constants.empty());
285 
286  const auto& type_info = constants.front()->get_type_info();
287  int16_t lit_off{-1};
288  for (size_t device_id = 0; device_id < constants.size(); ++device_id) {
289  const auto constant = constants[device_id];
290  const auto& crt_type_info = constant->get_type_info();
291  CHECK(type_info == crt_type_info);
292  const int16_t dev_lit_off =
293  cgen_state_->getOrAddLiteral(constant, enc_type, dict_id, device_id);
294  if (device_id) {
295  CHECK_EQ(lit_off, dev_lit_off);
296  } else {
297  lit_off = dev_lit_off;
298  }
299  }
300  CHECK_GE(lit_off, int16_t(0));
301 
302  std::vector<llvm::Value*> hoisted_literal_loads;
303  auto entry = cgen_state_->query_func_literal_loads_.find(lit_off);
304 
305  if (entry == cgen_state_->query_func_literal_loads_.end()) {
306  hoisted_literal_loads =
307  codegenHoistedConstantsLoads(type_info, enc_type, dict_id, lit_off);
308  cgen_state_->query_func_literal_loads_[lit_off] = hoisted_literal_loads;
309  } else {
310  hoisted_literal_loads = entry->second;
311  }
312 
313  std::vector<llvm::Value*> literal_placeholders = codegenHoistedConstantsPlaceholders(
314  type_info, enc_type, lit_off, hoisted_literal_loads);
315  return literal_placeholders;
316 }
int8_t tinyintval
Definition: sqltypes.h:203
#define CHECK_EQ(x, y)
Definition: Logger.h:205
std::vector< llvm::Value * > codegenHoistedConstants(const std::vector< const Analyzer::Constant *> &constants, const EncodingType enc_type, const int dict_id)
Definition: ConstantIR.cpp:279
bool is_time() const
Definition: sqltypes.h:484
bool is_array() const
Definition: sqltypes.h:486
bool is_string() const
Definition: sqltypes.h:478
bool is_boolean() const
Definition: sqltypes.h:485
Definition: sqltypes.h:48
bool is_integer() const
Definition: sqltypes.h:480
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:204
CgenState * cgen_state_
Executor * executor() const
llvm::Value * addStringConstant(const std::string &str)
Definition: CgenState.h:203
bool boolval
Definition: sqltypes.h:202
llvm::Function * query_func_
Definition: CgenState.h:351
std::unordered_map< llvm::Value *, HoistedLiteralLoadLocator > row_func_hoisted_literals_
Definition: CgenState.h:359
llvm::IRBuilder ir_builder_
Definition: CgenState.h:333
#define UNREACHABLE()
Definition: Logger.h:241
#define CHECK_GE(x, y)
Definition: Logger.h:210
std::unordered_map< int, std::vector< llvm::Value * > > query_func_literal_loads_
Definition: CgenState.h:353
bool is_timeinterval() const
Definition: sqltypes.h:489
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:319
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool is_decimal() const
Definition: sqltypes.h:481
int32_t intval
Definition: sqltypes.h:205
std::string to_string(char const *&&v)
static size_t literalBytes(const CgenState::LiteralValue &lit)
Definition: CgenState.h:361
float floatval
Definition: sqltypes.h:207
Datum get_constval() const
Definition: Analyzer.h:335
EncodingType
Definition: sqltypes.h:224
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:331
size_t getOrAddLiteral(const Analyzer::Constant *constant, const EncodingType enc_type, const int dict_id, const int device_id)
Definition: CgenState.h:62
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:162
std::vector< llvm::Value * > codegenHoistedConstantsLoads(const SQLTypeInfo &type_info, const EncodingType enc_type, const int dict_id, const int16_t lit_off)
Definition: ConstantIR.cpp:115
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:27
int64_t bigintval
Definition: sqltypes.h:206
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:312
int16_t smallintval
Definition: sqltypes.h:204
llvm::IRBuilder query_func_entry_ir_builder_
Definition: CgenState.h:352
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::string * stringval
Definition: sqltypes.h:211
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:303
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:26
bool get_is_null() const
Definition: Analyzer.h:334
Definition: sqltypes.h:51
Definition: sqltypes.h:52
static llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant, CgenState *cgen_state)
Definition: ConstantIR.cpp:85
Definition: sqltypes.h:40
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
boost::variant< int8_t, int16_t, int32_t, int64_t, float, double, std::pair< std::string, int >, std::string, std::vector< double >, std::vector< int32_t >, std::vector< int8_t >, std::pair< std::vector< int8_t >, int > > LiteralValue
Definition: CgenState.h:198
#define CHECK(condition)
Definition: Logger.h:197
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
Definition: sqltypes.h:44
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:300
double doubleval
Definition: sqltypes.h:208