mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
74ab96c971
SmallVectorTemplateCommon wants to know the address of the first element so it can detect whether it's in "small size" mode. The old implementation split the small array, creating the storage for the first element in SmallVectorTemplateCommon, and pulling the rest into SmallVectorStorage where we know the size of the array. This bloats SmallVector size 0 by the larger of sizeof(void*) and sizeof(T), and we're not even using the storage. The new implementation leaves the full small storage to SmallVectorStorage. To calculate the offset of the first element in SmallVectorTemplateCommon, we just need to know how far to jump, which we can calculate out-of-band. One subtlety is that we need SmallVectorStorage to be properly aligned even when the size is 0, to be sure that (for large alignments) we actually have the padding and it's well defined to do the pointer math. llvm-svn: 337820
67 lines
2.5 KiB
C++
67 lines
2.5 KiB
C++
//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the SmallVector class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
using namespace llvm;
|
|
|
|
// Check that no bytes are wasted and everything is well-aligned.
|
|
namespace {
|
|
struct Struct16B {
|
|
alignas(16) void *X;
|
|
};
|
|
struct Struct32B {
|
|
alignas(32) void *X;
|
|
};
|
|
}
|
|
static_assert(sizeof(SmallVector<void *, 0>) ==
|
|
sizeof(unsigned) * 2 + sizeof(void *),
|
|
"wasted space in SmallVector size 0");
|
|
static_assert(alignof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
|
|
"wrong alignment for 16-byte aligned T");
|
|
static_assert(alignof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
|
|
"wrong alignment for 32-byte aligned T");
|
|
static_assert(sizeof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
|
|
"missing padding for 16-byte aligned T");
|
|
static_assert(sizeof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
|
|
"missing padding for 32-byte aligned T");
|
|
static_assert(sizeof(SmallVector<void *, 1>) ==
|
|
sizeof(unsigned) * 2 + sizeof(void *) * 2,
|
|
"wasted space in SmallVector size 1");
|
|
|
|
/// grow_pod - This is an implementation of the grow() method which only works
|
|
/// on POD-like datatypes and is out of line to reduce code duplication.
|
|
void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity,
|
|
size_t TSize) {
|
|
// Ensure we can fit the new capacity in 32 bits.
|
|
if (MinCapacity > UINT32_MAX)
|
|
report_bad_alloc_error("SmallVector capacity overflow during allocation");
|
|
|
|
size_t NewCapacity = 2 * capacity() + 1; // Always grow.
|
|
NewCapacity =
|
|
std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX));
|
|
|
|
void *NewElts;
|
|
if (BeginX == FirstEl) {
|
|
NewElts = safe_malloc(NewCapacity * TSize);
|
|
|
|
// Copy the elements over. No need to run dtors on PODs.
|
|
memcpy(NewElts, this->BeginX, size() * TSize);
|
|
} else {
|
|
// If this wasn't grown from the inline copy, grow the allocated space.
|
|
NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
|
|
}
|
|
|
|
this->BeginX = NewElts;
|
|
this->Capacity = NewCapacity;
|
|
}
|