Index: include/llvm/Target/TargetData.h =================================================================== --- include/llvm/Target/TargetData.h (revision 163266) +++ include/llvm/Target/TargetData.h (working copy) @@ -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 @@ /// Target 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 @@ bool operator==(const TargetAlignElem &rhs) const; }; +/// Target 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; +}; + + /// TargetData - 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 @@ class TargetData : 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 LegalIntWidths; ///< Legal Integers. @@ -88,11 +106,16 @@ /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now, /// we don't. SmallVector Alignments; + DenseMap Pointers; /// InvalidAlignmentElem - This member is a signal that a requested alignment /// type and bit width were not found in the SmallVector. static const TargetAlignElem 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 @@ 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 @@ 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 TargetData object with default values, ensure that the /// target data pass is registered. void init(); @@ -142,11 +178,9 @@ TargetData(const TargetData &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) { } @@ -196,13 +230,45 @@ } /// Target pointer alignment - unsigned getPointerABIAlignment() const { return PointerABIAlign; } + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerABIAlignment(unsigned AS = 0) const { + DenseMap::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 - unsigned getPointerPrefAlignment() const { return PointerPrefAlign; } + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerPrefAlignment(unsigned AS = 0) const { + DenseMap::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.PrefAlign; + } /// Target 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::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.TypeBitWidth; + } /// Target 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::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return 8*val->second.TypeBitWidth; + } /// Size examples: /// @@ -281,8 +347,9 @@ /// 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. Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h (revision 163266) +++ include/llvm/Target/TargetLowering.h (working copy) @@ -142,7 +142,10 @@ 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 @@ -1770,7 +1781,8 @@ const TargetData *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; Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp (revision 163266) +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp (working copy) @@ -584,7 +584,7 @@ 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; @@ -624,7 +624,7 @@ } 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. @@ -900,7 +900,7 @@ 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 @@ 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 @@ EVT::getEVT(IntegerType::get(OpTy->getContext(), BitSize), true); break; } - } else if (dyn_cast(OpTy)) { - OpInfo.ConstraintVT = MVT::getIntegerVT(8*TD->getPointerSize()); + } else if (PointerType *PT = dyn_cast(OpTy)) { + OpInfo.ConstraintVT = MVT::getIntegerVT( + 8*TD->getPointerSize(PT->getAddressSpace())); } else { OpInfo.ConstraintVT = EVT::getEVT(OpTy, true); } Index: lib/Target/TargetData.cpp =================================================================== --- lib/Target/TargetData.cpp (revision 163266) +++ lib/Target/TargetData.cpp (working copy) @@ -118,9 +118,36 @@ } const TargetAlignElem -TargetData::InvalidAlignmentElem = { (AlignTypeEnum)0xFF, 0, 0, 0 }; +TargetData::InvalidAlignmentElem = TargetAlignElem::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 +TargetData::InvalidPointerElem = PointerAlignElem::get(~0U, 0U, 0U, 0U); + +//===----------------------------------------------------------------------===// // TargetData Class Implementation //===----------------------------------------------------------------------===// @@ -136,9 +163,6 @@ LayoutMap = 0; LittleEndian = false; - PointerMemSize = 8; - PointerABIAlign = 8; - PointerPrefAlign = PointerABIAlign; StackNaturalAlign = 0; // Default alignments @@ -154,6 +178,7 @@ 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 TargetData::parseSpecifier(StringRef Desc, TargetData *td) { @@ -185,13 +210,14 @@ td->LittleEndian = true; break; case 'p': { - // Pointer size. + int AddrSpace = 0; + if (Specifier.size() > 1) { + AddrSpace = getInt(Specifier.substr(1)); + } 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 +226,6 @@ 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 +234,12 @@ 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': @@ -328,6 +353,21 @@ pref_align, bit_width)); } +void +TargetData::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::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 target wants for the specified datatype. unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, @@ -441,10 +481,19 @@ 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"); + for (DenseMap::const_iterator + pib = Pointers.begin(), pie = Pointers.end(); + pib != pie; ++pib) { + const PointerAlignElem &PI = pib->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 TargetAlignElem &AI = Alignments[i]; @@ -466,8 +515,11 @@ 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(Ty)->getAddressSpace(); + return getPointerSizeInBits(AS); + } case Type::ArrayTyID: { ArrayType *ATy = cast(Ty); return getTypeAllocSizeInBits(ATy->getElementType())*ATy->getNumElements(); @@ -515,10 +567,15 @@ 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(Ty)->getAddressSpace(); + return (abi_or_pref + ? getPointerABIAlignment(AS) + : getPointerPrefAlignment(AS)); + } case Type::ArrayTyID: return getAlignment(cast(Ty)->getElementType(), abi_or_pref); @@ -589,8 +646,8 @@ /// getIntPtrType - Return an unsigned integer type that is the same size or /// greater to the host pointer size. -IntegerType *TargetData::getIntPtrType(LLVMContext &C) const { - return IntegerType::get(C, getPointerSizeInBits()); +IntegerType *TargetData::getIntPtrType(LLVMContext &C, unsigned AddressSpace) const { + return IntegerType::get(C, getPointerSizeInBits(AddressSpace)); }