Пример #1
0
// Iterate over the tuples in the sorter in batches/vectors of the given size
void Sorter::VectorizedIterate(
    CodeGen &codegen, llvm::Value *sorter_ptr, uint32_t vector_size,
    Sorter::VectorizedIterateCallback &callback) const {
  llvm::Value *start_pos = GetStartPosition(codegen, sorter_ptr);

  llvm::Value *num_tuples = GetNumberOfStoredTuples(codegen, sorter_ptr);

  // Determine the number of bytes to skip per vector
  llvm::Value *vec_sz = codegen.Const32(vector_size);
  llvm::Value *tuple_size = GetTupleSize(codegen);
  llvm::Value *skip = codegen->CreateMul(vec_sz, tuple_size);

  lang::VectorizedLoop loop{
      codegen, num_tuples, vector_size, {{"pos", start_pos}}};
  {
    llvm::Value *curr_pos = loop.GetLoopVar(0);
    auto curr_range = loop.GetCurrentRange();

    // Provide an accessor into the sorted space
    SorterAccess sorter_access{*this, start_pos};

    // Issue the callback
    callback.ProcessEntries(codegen, curr_range.start, curr_range.end,
                            sorter_access);

    // Bump the pointer by the size of a tuple
    llvm::Value *next_pos = codegen->CreateInBoundsGEP(curr_pos, skip);
    loop.LoopEnd(codegen, {next_pos});
  }
}
Пример #2
0
codegen::Value Sorter::SorterAccess::LoadRowValue(
    CodeGen &codegen, Sorter::SorterAccess::Row &row,
    uint32_t column_index) const {
  if (row.row_pos_ == nullptr) {
    auto *tuple_size = sorter_.GetTupleSize(codegen);
    auto *skip = codegen->CreateMul(row.row_idx_, tuple_size);
    row.row_pos_ =
        codegen->CreateInBoundsGEP(codegen.ByteType(), start_pos_, skip);
  }

  const auto &storage_format = sorter_.GetStorageFormat();
  UpdateableStorage::NullBitmap null_bitmap{codegen, storage_format,
                                            row.row_pos_};
  if (!null_bitmap.IsNullable(column_index)) {
    return storage_format.GetValueSkipNull(codegen, row.row_pos_, column_index);
  } else {
    return storage_format.GetValue(codegen, row.row_pos_, column_index,
                                   null_bitmap);
  }
}
Пример #3
0
// Load a given column for the row with the given TID
codegen::Value TileGroup::LoadColumn(
    CodeGen &codegen, llvm::Value *tid,
    const TileGroup::ColumnLayout &layout) const {
  // We're calculating: col[tid] = col_start + (tid * col_stride)
  llvm::Value *col_address =
      codegen->CreateInBoundsGEP(codegen.ByteType(), layout.col_start_ptr,
                                 codegen->CreateMul(tid, layout.col_stride));

  // The value, length and is_null check
  llvm::Value *val = nullptr, *length = nullptr, *is_null = nullptr;

  // Column metadata
  bool is_nullable = schema_.AllowNull(layout.col_id);
  const auto &column = schema_.GetColumn(layout.col_id);
  const auto &sql_type = type::SqlType::LookupType(column.GetType());

  // Check if it's a string or numeric value
  if (sql_type.IsVariableLength()) {
    auto *varlen_type = VarlenProxy::GetType(codegen);
    auto *varlen_ptr_ptr = codegen->CreateBitCast(
        col_address, varlen_type->getPointerTo()->getPointerTo());
    if (is_nullable) {
      codegen::Varlen::GetPtrAndLength(
          codegen, codegen->CreateLoad(varlen_ptr_ptr), val, length, is_null);
    } else {
      codegen::Varlen::SafeGetPtrAndLength(
          codegen, codegen->CreateLoad(varlen_ptr_ptr), val, length);
    }
    PL_ASSERT(val != nullptr && length != nullptr);
  } else {
    // Get the LLVM type of the column
    llvm::Type *col_type = nullptr, *col_len_type = nullptr;
    sql_type.GetTypeForMaterialization(codegen, col_type, col_len_type);
    PL_ASSERT(col_type != nullptr && col_len_type == nullptr);

    // val = *(col_type*)col_address;
    val = codegen->CreateLoad(
        col_type,
        codegen->CreateBitCast(col_address, col_type->getPointerTo()));

    if (is_nullable) {
      // To check for NULL, we need to perform a comparison between the value we
      // just read from the table with the NULL value for the column's type. We
      // need to be careful that the runtime type of both values is not NULL to
      // bypass the type system's NULL checking logic.
      if (sql_type.TypeId() == peloton::type::TypeId::BOOLEAN) {
        is_null = type::Boolean::Instance().CheckNull(codegen, col_address);
      } else {
        auto val_tmp = codegen::Value{sql_type, val};
        auto null_val =
            codegen::Value{sql_type, sql_type.GetNullValue(codegen).GetValue()};
        auto val_is_null = val_tmp.CompareEq(codegen, null_val);
        PL_ASSERT(!val_is_null.IsNullable());
        is_null = val_is_null.GetValue();
      }
    }
  }

  // Names
  val->setName(column.GetName());
  if (length != nullptr) length->setName(column.GetName() + ".len");
  if (is_null != nullptr) is_null->setName(column.GetName() + ".null");

  // Return the value
  auto type = type::Type{column.GetType(), is_nullable};
  return codegen::Value{type, val, length, is_null};
}