diff options
author | Chris Lattner <sabre@nondot.org> | 2012-01-23 22:57:10 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2012-01-23 22:57:10 +0000 |
commit | 27dd9cf5d1ec831a1cd0766580e6d1177a9800a3 (patch) | |
tree | 0d46a1cdc6cf49f0b395a3ad8b3e6a9ffd2d00da | |
parent | 4302a4965c4fffcecee23210dd1910d8d2c88259 (diff) | |
download | external_llvm-27dd9cf5d1ec831a1cd0766580e6d1177a9800a3.zip external_llvm-27dd9cf5d1ec831a1cd0766580e6d1177a9800a3.tar.gz external_llvm-27dd9cf5d1ec831a1cd0766580e6d1177a9800a3.tar.bz2 |
start the implementation of a new ConstantDataVector and ConstantDataArray
classes, per PR1324. Not all of their helper functions are implemented,
nothing creates them, and the rest of the compiler doesn't handle them yet.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148741 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Constants.h | 164 | ||||
-rw-r--r-- | include/llvm/Value.h | 2 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 148 | ||||
-rw-r--r-- | lib/VMCore/LLVMContextImpl.cpp | 5 | ||||
-rw-r--r-- | lib/VMCore/LLVMContextImpl.h | 3 |
5 files changed, 319 insertions, 3 deletions
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 3182add..022ac2d 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -34,6 +34,7 @@ class IntegerType; class StructType; class PointerType; class VectorType; +class SequentialType; template<class ConstantClass, class TypeClass, class ValType> struct ConstantCreator; @@ -298,7 +299,6 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - friend struct ConstantCreator<ConstantAggregateZero, Type, char>; void *operator new(size_t, unsigned); // DO NOT IMPLEMENT ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT protected: @@ -503,7 +503,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - friend struct ConstantCreator<ConstantPointerNull, PointerType, char>; void *operator new(size_t, unsigned); // DO NOT IMPLEMENT ConstantPointerNull(const ConstantPointerNull &); // DO NOT IMPLEMENT protected: @@ -535,6 +534,166 @@ public: return V->getValueID() == ConstantPointerNullVal; } }; + +//===----------------------------------------------------------------------===// +/// ConstantDataSequential - A vector or array of data that contains no +/// relocations, and whose element type is a simple 1/2/4/8-byte integer or +/// float/double. This is the common base class of ConstantDataArray and +/// ConstantDataVector. +/// +class ConstantDataSequential : public Constant { + friend class LLVMContextImpl; + /// DataElements - A pointer to the bytes underlying this constant (which is + /// owned by the uniquing StringMap). + const char *DataElements; + + /// Next - This forms a link list of ConstantDataSequential nodes that have + /// the same value but different type. For example, 0,0,0,1 could be a 4 + /// element array of i8, or a 1-element array of i32. They'll both end up in + /// the same StringMap bucket, linked up. + ConstantDataSequential *Next; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantDataSequential(const ConstantDataSequential &); // DO NOT IMPLEMENT +protected: + explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) + : Constant(ty, VT, 0, 0), DataElements(Data) {} + ~ConstantDataSequential() { delete Next; } + + static Constant *getImpl(StringRef Bytes, Type *Ty); + +protected: + // allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + + virtual void destroyConstant(); + + /// getElementAsInteger - If this is a sequential container of integers (of + /// any size), return the specified element in the low bits of a uint64_t. + uint64_t getElementAsInteger(unsigned i) const; + + /// getElementAsAPFloat - If this is a sequential container of floating point + /// type, return the specified element as an APFloat. + APFloat getElementAsAPFloat(unsigned i) const; + + /// getElementAsFloat - If this is an sequential container of floats, return + /// the specified element as a float. + float getElementAsFloat(unsigned i) const; + + /// getElementAsDouble - If this is an sequential container of doubles, return + /// the specified element as a float. + double getElementAsDouble(unsigned i) const; + + /// getElementAsConstant - Return a Constant for a specified index's element. + /// Note that this has to compute a new constant to return, so it isn't as + /// efficient as getElementAsInteger/Float/Double. + Constant *getElementAsConstant(unsigned i) const; + + /// getType - Specialize the getType() method to always return a + /// SequentialType, which reduces the amount of casting needed in parts of the + /// compiler. + inline SequentialType *getType() const { + return reinterpret_cast<SequentialType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const ConstantDataSequential *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantDataArrayVal || + V->getValueID() == ConstantDataVectorVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantDataArray - An array of data that contains no relocations, and whose +/// element type is a simple 1/2/4/8-byte integer or float/double. +/// +class ConstantDataArray : public ConstantDataSequential { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantDataArray(const ConstantDataArray &); // DO NOT IMPLEMENT + virtual void anchor(); + friend class ConstantDataSequential; + explicit ConstantDataArray(Type *ty, const char *Data) + : ConstantDataSequential(ty, ConstantDataArrayVal, Data) {} +protected: + // allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + + /// get() constructors - Return a constant with array type with an element + /// count and element type matching the ArrayRef passed in. Note that this + /// can return a ConstantAggregateZero object. + static Constant *get(ArrayRef<uint8_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<uint16_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<uint32_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<uint64_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<float> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<double> Elts, LLVMContext &Context); + + /// getType - Specialize the getType() method to always return an ArrayType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline ArrayType *getType() const { + return reinterpret_cast<ArrayType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const ConstantDataArray *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantDataArrayVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantDataVector - A vector of data that contains no relocations, and +/// whose element type is a simple 1/2/4/8-byte integer or float/double. +/// +class ConstantDataVector : public ConstantDataSequential { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantDataVector(const ConstantDataVector &); // DO NOT IMPLEMENT + virtual void anchor(); + friend class ConstantDataSequential; + explicit ConstantDataVector(Type *ty, const char *Data) + : ConstantDataSequential(ty, ConstantDataVectorVal, Data) {} +protected: + // allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + + /// get() constructors - Return a constant with vector type with an element + /// count and element type matching the ArrayRef passed in. Note that this + /// can return a ConstantAggregateZero object. + static Constant *get(ArrayRef<uint8_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<uint16_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<uint32_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<uint64_t> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<float> Elts, LLVMContext &Context); + static Constant *get(ArrayRef<double> Elts, LLVMContext &Context); + + /// getType - Specialize the getType() method to always return a VectorType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline VectorType *getType() const { + return reinterpret_cast<VectorType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const ConstantDataVector *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantDataVectorVal; + } +}; + + /// BlockAddress - The address of a basic block. /// @@ -893,7 +1052,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - friend struct ConstantCreator<UndefValue, Type, char>; void *operator new(size_t, unsigned); // DO NOT IMPLEMENT UndefValue(const UndefValue &); // DO NOT IMPLEMENT protected: diff --git a/include/llvm/Value.h b/include/llvm/Value.h index b12744c..9c658cf 100644 --- a/include/llvm/Value.h +++ b/include/llvm/Value.h @@ -193,6 +193,8 @@ public: BlockAddressVal, // This is an instance of BlockAddress ConstantExprVal, // This is an instance of ConstantExpr ConstantAggregateZeroVal, // This is an instance of ConstantAggregateZero + ConstantDataArrayVal, // This is an instance of ConstantDataArray + ConstantDataVectorVal, // This is an instance of ConstantDataVector ConstantIntVal, // This is an instance of ConstantInt ConstantFPVal, // This is an instance of ConstantFP ConstantArrayVal, // This is an instance of ConstantArray diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index e9b433b..3b52a7c 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1913,6 +1913,154 @@ GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList, OperandList[i+1] = IdxList[i]; } +//===----------------------------------------------------------------------===// +// ConstantData* implementations + +void ConstantDataArray::anchor() {} +void ConstantDataVector::anchor() {} + +/// isAllZeros - return true if the array is empty or all zeros. +static bool isAllZeros(StringRef Arr) { + for (StringRef::iterator I = Arr.begin(), E = Arr.end(); I != E; ++I) + if (*I != 0) + return false; + return true; +} +/// getImpl - This is the underlying implementation of all of the +/// ConstantDataSequential::get methods. They all thunk down to here, providing +/// the correct element type. We take the bytes in as an StringRef because +/// we *want* an underlying "char*" to avoid TBAA type punning violations. +Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { + // If the elements are all zero, return a CAZ, which is more dense. + if (isAllZeros(Elements)) + return ConstantAggregateZero::get(Ty); + + // Do a lookup to see if we have already formed one of these. + StringMap<ConstantDataSequential*>::MapEntryTy &Slot = + Ty->getContext().pImpl->CDSConstants.GetOrCreateValue(Elements); + + // The bucket can point to a linked list of different CDS's that have the same + // body but different types. For example, 0,0,0,1 could be a 4 element array + // of i8, or a 1-element array of i32. They'll both end up in the same + /// StringMap bucket, linked up by their Next pointers. Walk the list. + ConstantDataSequential **Entry = &Slot.getValue(); + for (ConstantDataSequential *Node = *Entry; Node != 0; + Entry = &Node->Next, Node = *Entry) + if (Node->getType() == Ty) + return Node; + + // Okay, we didn't get a hit. Create a node of the right class, link it in, + // and return it. + if (isa<ArrayType>(Ty)) + return *Entry = new ConstantDataArray(Ty, Slot.getKeyData()); + + assert(isa<VectorType>(Ty)); + return *Entry = new ConstantDataVector(Ty, Slot.getKeyData()); +} + +void ConstantDataSequential::destroyConstant() { + uint64_t ByteSize = + getType()->getElementType()->getPrimitiveSizeInBits()/8 * + getType()->getElementType()->getNumElements(); + + // Remove the constant from the StringMap. + StringMap<ConstantDataSequential*> &CDSConstants = + getType()->getContext().pImpl->CDSConstants; + + StringMap<ConstantDataSequential*>::iterator Slot = + CDSConstants.find(StringRef(DataElements, ByteSize)); + + assert(Slot != CDSConstants.end() && "CDS not found in uniquing table"); + + ConstantDataSequential **Entry = &Slot->getValue(); + + // Remove the entry from the hash table. + if ((*Entry)->Next == 0) { + // If there is only one value in the bucket (common case) it must be this + // entry, and removing the entry should remove the bucket completely. + assert((*Entry) == this && "Hash mismatch in ConstantDataSequential"); + getContext().pImpl->CDSConstants.erase(Slot); + } else { + // Otherwise, there are multiple entries linked off the bucket, unlink the + // node we care about but keep the bucket around. + for (ConstantDataSequential *Node = *Entry; ; + Entry = &Node->Next, Node = *Entry) { + assert(Node && "Didn't find entry in its uniquing hash table!"); + // If we found our entry, unlink it from the list and we're done. + if (Node == this) { + *Entry = Node->Next; + break; + } + } + } + + // If we were part of a list, make sure that we don't delete the list that is + // still owned by the uniquing map. + Next = 0; + + // Finally, actually delete it. + destroyConstantImpl(); +} + +/// get() constructors - Return a constant with array type with an element +/// count and element type matching the ArrayRef passed in. Note that this +/// can return a ConstantAggregateZero object. +Constant *ConstantDataArray::get(ArrayRef<uint8_t> Elts, LLVMContext &Context) { + Type *Ty = ArrayType::get(Type::getInt8Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*1), Ty); +} +Constant *ConstantDataArray::get(ArrayRef<uint16_t> Elts, LLVMContext &Context){ + Type *Ty = ArrayType::get(Type::getInt16Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*2), Ty); +} +Constant *ConstantDataArray::get(ArrayRef<uint32_t> Elts, LLVMContext &Context){ + Type *Ty = ArrayType::get(Type::getInt32Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); +} +Constant *ConstantDataArray::get(ArrayRef<uint64_t> Elts, LLVMContext &Context){ + Type *Ty = ArrayType::get(Type::getInt64Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); +} +Constant *ConstantDataArray::get(ArrayRef<float> Elts, LLVMContext &Context) { + Type *Ty = ArrayType::get(Type::getFloatTy(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); +} +Constant *ConstantDataArray::get(ArrayRef<double> Elts, LLVMContext &Context) { + Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); +} + + +/// get() constructors - Return a constant with vector type with an element +/// count and element type matching the ArrayRef passed in. Note that this +/// can return a ConstantAggregateZero object. +Constant *ConstantDataVector::get(ArrayRef<uint8_t> Elts, LLVMContext &Context) { + Type *Ty = VectorType::get(Type::getInt8Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*1), Ty); +} +Constant *ConstantDataVector::get(ArrayRef<uint16_t> Elts, LLVMContext &Context){ + Type *Ty = VectorType::get(Type::getInt16Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*2), Ty); +} +Constant *ConstantDataVector::get(ArrayRef<uint32_t> Elts, LLVMContext &Context){ + Type *Ty = VectorType::get(Type::getInt32Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); +} +Constant *ConstantDataVector::get(ArrayRef<uint64_t> Elts, LLVMContext &Context){ + Type *Ty = VectorType::get(Type::getInt64Ty(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); +} +Constant *ConstantDataVector::get(ArrayRef<float> Elts, LLVMContext &Context) { + Type *Ty = VectorType::get(Type::getFloatTy(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); +} +Constant *ConstantDataVector::get(ArrayRef<double> Elts, LLVMContext &Context) { + Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size()); + return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); +} + + + //===----------------------------------------------------------------------===// // replaceUsesOfWithOnConstant implementations diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index 2eaebac..15c5c24 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -79,6 +79,11 @@ LLVMContextImpl::~LLVMContextImpl() { DeleteContainerSeconds(IntConstants); DeleteContainerSeconds(FPConstants); + for (StringMap<ConstantDataSequential*>::iterator I = CDSConstants.begin(), + E = CDSConstants.end(); I != E; ++I) + delete I->second; + CDSConstants.clear(); + // Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet // and the NonUniquedMDNodes sets, so copy the values out first. SmallVector<MDNode*, 8> MDNodes; diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index f8abdf1..ca37ffa 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -156,6 +156,9 @@ public: DenseMap<Type*, UndefValue*> UVConstants; + StringMap<ConstantDataSequential*> CDSConstants; + + DenseMap<std::pair<Function*, BasicBlock*> , BlockAddress*> BlockAddresses; ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr> ExprConstants; |