Add in the first step of the multiple pointer support. This adds in support to the data layout for specifying a per address space pointer size.

The next step is to update the optimizers to allow them to optimize the different address spaces with this information.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165505 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Micah Villmow 2012-10-09 16:06:12 +00:00
parent 942895d371
commit 7d66146868
4 changed files with 190 additions and 49 deletions

View File

@ -22,6 +22,7 @@
#include "llvm/Pass.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@ -47,8 +48,8 @@ enum AlignTypeEnum {
/// Layout alignment element.
///
/// Stores the alignment data associated with a given alignment type (pointer,
/// integer, vector, float) and type bit width.
/// Stores the alignment data associated with a given alignment type (integer,
/// vector, float) and type bit width.
///
/// @note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
@ -65,6 +66,26 @@ struct LayoutAlignElem {
bool operator==(const LayoutAlignElem &rhs) const;
};
/// Layout pointer alignment element.
///
/// Stores the alignment data associated with a given pointer and address space.
///
/// @note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
struct PointerAlignElem {
unsigned ABIAlign; ///< ABI alignment for this type/bitw
unsigned PrefAlign; ///< Pref. alignment for this type/bitw
uint32_t TypeBitWidth; ///< Type bit width
uint32_t AddressSpace; ///< Address space for the pointer type
/// Initializer
static PointerAlignElem get(uint32_t addr_space, unsigned abi_align,
unsigned pref_align, uint32_t bit_width);
/// Equality predicate
bool operator==(const PointerAlignElem &rhs) const;
};
/// DataLayout - This class holds a parsed version of the target data layout
/// string in a module and provides methods for querying it. The target data
/// layout string is specified *by the target* - a frontend generating LLVM IR
@ -74,9 +95,6 @@ struct LayoutAlignElem {
class DataLayout : public ImmutablePass {
private:
bool LittleEndian; ///< Defaults to false
unsigned PointerMemSize; ///< Pointer size in bytes
unsigned PointerABIAlign; ///< Pointer ABI alignment
unsigned PointerPrefAlign; ///< Pointer preferred alignment
unsigned StackNaturalAlign; ///< Stack natural alignment
SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
@ -88,11 +106,16 @@ private:
/// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now,
/// we don't.
SmallVector<LayoutAlignElem, 16> Alignments;
DenseMap<unsigned, PointerAlignElem> Pointers;
/// InvalidAlignmentElem - This member is a signal that a requested alignment
/// type and bit width were not found in the SmallVector.
static const LayoutAlignElem InvalidAlignmentElem;
/// InvalidPointerElem - This member is a signal that a requested pointer
/// type and bit width were not found in the DenseSet.
static const PointerAlignElem InvalidPointerElem;
// The StructType -> StructLayout map.
mutable void *LayoutMap;
@ -101,6 +124,11 @@ private:
unsigned pref_align, uint32_t bit_width);
unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
bool ABIAlign, Type *Ty) const;
//! Set/initialize pointer alignments
void setPointerAlignment(uint32_t addr_space, unsigned abi_align,
unsigned pref_align, uint32_t bit_width);
//! Internal helper method that returns requested alignment for type.
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
@ -112,6 +140,14 @@ private:
return &align != &InvalidAlignmentElem;
}
/// Valid pointer predicate.
///
/// Predicate that tests a PointerAlignElem reference returned by get() against
/// InvalidPointerElem.
bool validPointer(const PointerAlignElem &align) const {
return &align != &InvalidPointerElem;
}
/// Initialise a DataLayout object with default values, ensure that the
/// target data pass is registered.
void init();
@ -143,11 +179,9 @@ public:
DataLayout(const DataLayout &TD) :
ImmutablePass(ID),
LittleEndian(TD.isLittleEndian()),
PointerMemSize(TD.PointerMemSize),
PointerABIAlign(TD.PointerABIAlign),
PointerPrefAlign(TD.PointerPrefAlign),
LegalIntWidths(TD.LegalIntWidths),
Alignments(TD.Alignments),
Pointers(TD.Pointers),
LayoutMap(0)
{ }
@ -197,14 +231,45 @@ public:
}
/// Layout pointer alignment
unsigned getPointerABIAlignment() const { return PointerABIAlign; }
/// Return layout's alignment for stack-based pointers
unsigned getPointerPrefAlignment() const { return PointerPrefAlign; }
/// FIXME: The defaults need to be removed once all of
/// the backends/clients are updated.
unsigned getPointerABIAlignment(unsigned AS = 0) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
}
return val->second.ABIAlign;
}
/// Return target's alignment for stack-based pointers
/// FIXME: The defaults need to be removed once all of
/// the backends/clients are updated.
unsigned getPointerPrefAlignment(unsigned AS = 0) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
}
return val->second.PrefAlign;
}
/// Layout pointer size
unsigned getPointerSize() const { return PointerMemSize; }
/// FIXME: The defaults need to be removed once all of
/// the backends/clients are updated.
unsigned getPointerSize(unsigned AS = 0) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
}
return val->second.TypeBitWidth;
}
/// Layout pointer size, in bits
unsigned getPointerSizeInBits() const { return 8*PointerMemSize; }
/// FIXME: The defaults need to be removed once all of
/// the backends/clients are updated.
unsigned getPointerSizeInBits(unsigned AS = 0) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
}
return 8*val->second.TypeBitWidth;
}
/// Size examples:
///
/// Type SizeInBits StoreSizeInBits AllocSizeInBits[*]
@ -282,8 +347,9 @@ public:
/// getIntPtrType - Return an unsigned integer type that is the same size or
/// greater to the host pointer size.
///
IntegerType *getIntPtrType(LLVMContext &C) const;
/// FIXME: Need to remove the default argument when the rest of the LLVM code
/// base has been updated.
IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const;
/// getIndexedOffset - return the offset from the beginning of the type for
/// the specified indices. This is used to implement getelementptr.

View File

@ -143,7 +143,10 @@ public:
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
MVT getPointerTy() const { return PointerTy; }
// Return the pointer type for the given address space, defaults to
// the pointer type from the data layout.
// FIXME: The default needs to be removed once all the code is updated.
virtual MVT getPointerTy(uint32_t addrspace = 0) const { return PointerTy; }
virtual MVT getShiftAmountTy(EVT LHSTy) const;
/// isSelectExpensive - Return true if the select operation is expensive for
@ -1777,7 +1780,8 @@ private:
const DataLayout *TD;
const TargetLoweringObjectFile &TLOF;
/// PointerTy - The type to use for pointers, usually i32 or i64.
/// PointerTy - The type to use for pointers for the default address space,
/// usually i32 or i64.
///
MVT PointerTy;

View File

@ -584,7 +584,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm,
setOperationAction(ISD::TRAP, MVT::Other, Expand);
IsLittleEndian = TD->isLittleEndian();
PointerTy = MVT::getIntegerVT(8*TD->getPointerSize());
PointerTy = MVT::getIntegerVT(8*TD->getPointerSize(0));
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray));
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
@ -625,7 +625,7 @@ TargetLowering::~TargetLowering() {
}
MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const {
return MVT::getIntegerVT(8*TD->getPointerSize());
return MVT::getIntegerVT(8*TD->getPointerSize(0));
}
/// canOpTrap - Returns true if the operation can trap for the value type.
@ -901,7 +901,7 @@ const char *TargetLowering::getTargetNodeName(unsigned Opcode) const {
EVT TargetLowering::getSetCCResultType(EVT VT) const {
assert(!VT.isVector() && "No default SetCC type for vectors!");
return PointerTy.SimpleTy;
return getPointerTy(0).SimpleTy;
}
MVT::SimpleValueType TargetLowering::getCmpLibcallReturnType() const {
@ -1061,7 +1061,7 @@ SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table,
if ((JTEncoding == MachineJumpTableInfo::EK_GPRel64BlockAddress) ||
(JTEncoding == MachineJumpTableInfo::EK_GPRel32BlockAddress))
return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy());
return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy(0));
return Table;
}
@ -2953,8 +2953,9 @@ TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints(
EVT::getEVT(IntegerType::get(OpTy->getContext(), BitSize), true);
break;
}
} else if (dyn_cast<PointerType>(OpTy)) {
OpInfo.ConstraintVT = MVT::getIntegerVT(8*TD->getPointerSize());
} else if (PointerType *PT = dyn_cast<PointerType>(OpTy)) {
OpInfo.ConstraintVT = MVT::getIntegerVT(
8*TD->getPointerSize(PT->getAddressSpace()));
} else {
OpInfo.ConstraintVT = EVT::getEVT(OpTy, true);
}

View File

@ -118,7 +118,35 @@ LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const {
}
const LayoutAlignElem
DataLayout::InvalidAlignmentElem = { (AlignTypeEnum)0xFF, 0, 0, 0 };
DataLayout::InvalidAlignmentElem =
LayoutAlignElem::get((AlignTypeEnum) -1, 0, 0, 0);
//===----------------------------------------------------------------------===//
// PointerAlignElem, PointerAlign support
//===----------------------------------------------------------------------===//
PointerAlignElem
PointerAlignElem::get(uint32_t addr_space, unsigned abi_align,
unsigned pref_align, uint32_t bit_width) {
assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
PointerAlignElem retval;
retval.AddressSpace = addr_space;
retval.ABIAlign = abi_align;
retval.PrefAlign = pref_align;
retval.TypeBitWidth = bit_width;
return retval;
}
bool
PointerAlignElem::operator==(const PointerAlignElem &rhs) const {
return (ABIAlign == rhs.ABIAlign
&& AddressSpace == rhs.AddressSpace
&& PrefAlign == rhs.PrefAlign
&& TypeBitWidth == rhs.TypeBitWidth);
}
const PointerAlignElem
DataLayout::InvalidPointerElem = PointerAlignElem::get(~0U, 0U, 0U, 0U);
//===----------------------------------------------------------------------===//
// DataLayout Class Implementation
@ -136,9 +164,6 @@ void DataLayout::init() {
LayoutMap = 0;
LittleEndian = false;
PointerMemSize = 8;
PointerABIAlign = 8;
PointerPrefAlign = PointerABIAlign;
StackNaturalAlign = 0;
// Default alignments
@ -154,6 +179,7 @@ void DataLayout::init() {
setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ...
setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ...
setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct
setPointerAlignment(0, 8, 8, 8);
}
std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
@ -185,13 +211,16 @@ std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
td->LittleEndian = true;
break;
case 'p': {
// Pointer size.
int AddrSpace = 0;
if (Specifier.size() > 1) {
AddrSpace = getInt(Specifier.substr(1));
if (AddrSpace < 0 || AddrSpace > (1 << 24))
return "Invalid address space, must be a positive 24bit integer";
}
Split = Token.split(':');
int PointerMemSizeBits = getInt(Split.first);
if (PointerMemSizeBits < 0 || PointerMemSizeBits % 8 != 0)
return "invalid pointer size, must be a positive 8-bit multiple";
if (td)
td->PointerMemSize = PointerMemSizeBits / 8;
// Pointer ABI alignment.
Split = Split.second.split(':');
@ -200,8 +229,6 @@ std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
return "invalid pointer ABI alignment, "
"must be a positive 8-bit multiple";
}
if (td)
td->PointerABIAlign = PointerABIAlignBits / 8;
// Pointer preferred alignment.
Split = Split.second.split(':');
@ -210,11 +237,12 @@ std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
return "invalid pointer preferred alignment, "
"must be a positive 8-bit multiple";
}
if (td) {
td->PointerPrefAlign = PointerPrefAlignBits / 8;
if (td->PointerPrefAlign == 0)
td->PointerPrefAlign = td->PointerABIAlign;
}
if (PointerPrefAlignBits == 0)
PointerPrefAlignBits = PointerABIAlignBits;
if (td)
td->setPointerAlignment(AddrSpace, PointerABIAlignBits/8,
PointerPrefAlignBits/8, PointerMemSizeBits/8);
break;
}
case 'i':
@ -330,6 +358,21 @@ DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
pref_align, bit_width));
}
void
DataLayout::setPointerAlignment(uint32_t addr_space, unsigned abi_align,
unsigned pref_align, uint32_t bit_width) {
assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
DenseMap<unsigned,PointerAlignElem>::iterator val = Pointers.find(addr_space);
if (val == Pointers.end()) {
Pointers[addr_space] = PointerAlignElem::get(addr_space,
abi_align, pref_align, bit_width);
} else {
val->second.ABIAlign = abi_align;
val->second.PrefAlign = pref_align;
val->second.TypeBitWidth = bit_width;
}
}
/// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or
/// preferred if ABIInfo = false) the layout wants for the specified datatype.
unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType,
@ -443,10 +486,28 @@ std::string DataLayout::getStringRepresentation() const {
std::string Result;
raw_string_ostream OS(Result);
OS << (LittleEndian ? "e" : "E")
<< "-p:" << PointerMemSize*8 << ':' << PointerABIAlign*8
<< ':' << PointerPrefAlign*8
<< "-S" << StackNaturalAlign*8;
OS << (LittleEndian ? "e" : "E");
SmallVector<unsigned, 8> addrSpaces;
// Lets get all of the known address spaces and sort them
// into increasing order so that we can emit the string
// in a cleaner format.
for (DenseMap<unsigned, PointerAlignElem>::const_iterator
pib = Pointers.begin(), pie = Pointers.end();
pib != pie; ++pib) {
addrSpaces.push_back(pib->first);
}
std::sort(addrSpaces.begin(), addrSpaces.end());
for (SmallVector<unsigned, 8>::iterator asb = addrSpaces.begin(),
ase = addrSpaces.end(); asb != ase; ++asb) {
const PointerAlignElem &PI = Pointers.find(*asb)->second;
OS << "-p";
if (PI.AddressSpace) {
OS << PI.AddressSpace;
}
OS << ":" << PI.TypeBitWidth*8 << ':' << PI.ABIAlign*8
<< ':' << PI.PrefAlign*8;
}
OS << "-S" << StackNaturalAlign*8;
for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
const LayoutAlignElem &AI = Alignments[i];
@ -468,8 +529,11 @@ uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
switch (Ty->getTypeID()) {
case Type::LabelTyID:
case Type::PointerTyID:
return getPointerSizeInBits();
return getPointerSizeInBits(0);
case Type::PointerTyID: {
unsigned AS = dyn_cast<PointerType>(Ty)->getAddressSpace();
return getPointerSizeInBits(AS);
}
case Type::ArrayTyID: {
ArrayType *ATy = cast<ArrayType>(Ty);
return getTypeAllocSizeInBits(ATy->getElementType())*ATy->getNumElements();
@ -517,10 +581,15 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
switch (Ty->getTypeID()) {
// Early escape for the non-numeric types.
case Type::LabelTyID:
case Type::PointerTyID:
return (abi_or_pref
? getPointerABIAlignment()
: getPointerPrefAlignment());
? getPointerABIAlignment(0)
: getPointerPrefAlignment(0));
case Type::PointerTyID: {
unsigned AS = dyn_cast<PointerType>(Ty)->getAddressSpace();
return (abi_or_pref
? getPointerABIAlignment(AS)
: getPointerPrefAlignment(AS));
}
case Type::ArrayTyID:
return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref);
@ -591,8 +660,9 @@ unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const {
/// getIntPtrType - Return an unsigned integer type that is the same size or
/// greater to the host pointer size.
IntegerType *DataLayout::getIntPtrType(LLVMContext &C) const {
return IntegerType::get(C, getPointerSizeInBits());
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
unsigned AddressSpace) const {
return IntegerType::get(C, getPointerSizeInBits(AddressSpace));
}