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