diff options
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AutoUpgrade.cpp | 36 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 90 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 336 | ||||
-rw-r--r-- | lib/VMCore/Core.cpp | 3 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 2 | ||||
-rw-r--r-- | lib/VMCore/LLVMContext.cpp | 59 | ||||
-rw-r--r-- | lib/VMCore/LLVMContextImpl.cpp | 386 | ||||
-rw-r--r-- | lib/VMCore/LLVMContextImpl.h | 350 |
8 files changed, 488 insertions, 774 deletions
diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index 016a339..ca2e57d 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -271,20 +271,20 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Context.getPointerTypeUnqual(Type::DoubleTy), "upgraded.", CI); Value *Load = new LoadInst(Addr, "upgraded.", false, 8, CI); - Value *Idx = Context.getConstantInt(Type::Int32Ty, 0); + Value *Idx = ConstantInt::get(Type::Int32Ty, 0); Op1 = InsertElementInst::Create(Op1, Load, Idx, "upgraded.", CI); if (isLoadH) { - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 0)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 2)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 0)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 2)); } else { - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 2)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 1)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 2)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 1)); } Value *Mask = Context.getConstantVector(Idxs); SI = new ShuffleVectorInst(Op0, Op1, Mask, "upgraded.", CI); } else if (isMovL) { - Constant *Zero = Context.getConstantInt(Type::Int32Ty, 0); + Constant *Zero = ConstantInt::get(Type::Int32Ty, 0); Idxs.push_back(Zero); Idxs.push_back(Zero); Idxs.push_back(Zero); @@ -292,32 +292,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Value *ZeroV = Context.getConstantVector(Idxs); Idxs.clear(); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 4)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 5)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 2)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 3)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 4)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 5)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 2)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 3)); Value *Mask = Context.getConstantVector(Idxs); SI = new ShuffleVectorInst(ZeroV, Op0, Mask, "upgraded.", CI); } else if (isMovSD || isUnpckhPD || isUnpcklPD || isPunpckhQPD || isPunpcklQPD) { Value *Op1 = CI->getOperand(2); if (isMovSD) { - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 2)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 1)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 2)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 1)); } else if (isUnpckhPD || isPunpckhQPD) { - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 1)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 3)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 1)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 3)); } else { - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 0)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, 2)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 0)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 2)); } Value *Mask = Context.getConstantVector(Idxs); SI = new ShuffleVectorInst(Op0, Op1, Mask, "upgraded.", CI); } else if (isShufPD) { Value *Op1 = CI->getOperand(2); unsigned MaskVal = cast<ConstantInt>(CI->getOperand(3))->getZExtValue(); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, MaskVal & 1)); - Idxs.push_back(Context.getConstantInt(Type::Int32Ty, + Idxs.push_back(ConstantInt::get(Type::Int32Ty, MaskVal & 1)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, ((MaskVal >> 1) & 1)+2)); Value *Mask = Context.getConstantVector(Idxs); SI = new ShuffleVectorInst(Op0, Op1, Mask, "upgraded.", CI); diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 0e4bf6c..a26bee8 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -171,7 +171,7 @@ static Constant *FoldBitCast(LLVMContext &Context, // Handle ConstantFP input. if (const ConstantFP *FP = dyn_cast<ConstantFP>(V)) // FP -> Integral. - return Context.getConstantInt(FP->getValueAPF().bitcastToAPInt()); + return ConstantInt::get(Context, FP->getValueAPF().bitcastToAPInt()); return 0; } @@ -258,7 +258,7 @@ Constant *llvm::ConstantFoldCastInstruction(LLVMContext &Context, (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, APFloat::rmTowardZero, &ignored); APInt Val(DestBitWidth, 2, x); - return Context.getConstantInt(Val); + return ConstantInt::get(Context, Val); } return 0; // Can't fold. case Instruction::IntToPtr: //always treated as unsigned @@ -267,7 +267,7 @@ Constant *llvm::ConstantFoldCastInstruction(LLVMContext &Context, return 0; // Other pointer types cannot be casted case Instruction::PtrToInt: // always treated as unsigned if (V->isNullValue()) // is it a null pointer value? - return Context.getConstantInt(DestTy, 0); + return ConstantInt::get(DestTy, 0); return 0; // Other pointer types cannot be casted case Instruction::UIToFP: case Instruction::SIToFP: @@ -287,7 +287,7 @@ Constant *llvm::ConstantFoldCastInstruction(LLVMContext &Context, uint32_t BitWidth = cast<IntegerType>(DestTy)->getBitWidth(); APInt Result(CI->getValue()); Result.zext(BitWidth); - return Context.getConstantInt(Result); + return ConstantInt::get(Context, Result); } return 0; case Instruction::SExt: @@ -295,7 +295,7 @@ Constant *llvm::ConstantFoldCastInstruction(LLVMContext &Context, uint32_t BitWidth = cast<IntegerType>(DestTy)->getBitWidth(); APInt Result(CI->getValue()); Result.sext(BitWidth); - return Context.getConstantInt(Result); + return ConstantInt::get(Context, Result); } return 0; case Instruction::Trunc: @@ -303,7 +303,7 @@ Constant *llvm::ConstantFoldCastInstruction(LLVMContext &Context, uint32_t BitWidth = cast<IntegerType>(DestTy)->getBitWidth(); APInt Result(CI->getValue()); Result.trunc(BitWidth); - return Context.getConstantInt(Result); + return ConstantInt::get(Context, Result); } return 0; case Instruction::BitCast: @@ -721,51 +721,51 @@ Constant *llvm::ConstantFoldBinaryInstruction(LLVMContext &Context, default: break; case Instruction::Add: - return Context.getConstantInt(C1V + C2V); + return ConstantInt::get(Context, C1V + C2V); case Instruction::Sub: - return Context.getConstantInt(C1V - C2V); + return ConstantInt::get(Context, C1V - C2V); case Instruction::Mul: - return Context.getConstantInt(C1V * C2V); + return ConstantInt::get(Context, C1V * C2V); case Instruction::UDiv: assert(!CI2->isNullValue() && "Div by zero handled above"); - return Context.getConstantInt(C1V.udiv(C2V)); + return ConstantInt::get(Context, C1V.udiv(C2V)); case Instruction::SDiv: assert(!CI2->isNullValue() && "Div by zero handled above"); if (C2V.isAllOnesValue() && C1V.isMinSignedValue()) return Context.getUndef(CI1->getType()); // MIN_INT / -1 -> undef - return Context.getConstantInt(C1V.sdiv(C2V)); + return ConstantInt::get(Context, C1V.sdiv(C2V)); case Instruction::URem: assert(!CI2->isNullValue() && "Div by zero handled above"); - return Context.getConstantInt(C1V.urem(C2V)); + return ConstantInt::get(Context, C1V.urem(C2V)); case Instruction::SRem: assert(!CI2->isNullValue() && "Div by zero handled above"); if (C2V.isAllOnesValue() && C1V.isMinSignedValue()) return Context.getUndef(CI1->getType()); // MIN_INT % -1 -> undef - return Context.getConstantInt(C1V.srem(C2V)); + return ConstantInt::get(Context, C1V.srem(C2V)); case Instruction::And: - return Context.getConstantInt(C1V & C2V); + return ConstantInt::get(Context, C1V & C2V); case Instruction::Or: - return Context.getConstantInt(C1V | C2V); + return ConstantInt::get(Context, C1V | C2V); case Instruction::Xor: - return Context.getConstantInt(C1V ^ C2V); + return ConstantInt::get(Context, C1V ^ C2V); case Instruction::Shl: { uint32_t shiftAmt = C2V.getZExtValue(); if (shiftAmt < C1V.getBitWidth()) - return Context.getConstantInt(C1V.shl(shiftAmt)); + return ConstantInt::get(Context, C1V.shl(shiftAmt)); else return Context.getUndef(C1->getType()); // too big shift is undef } case Instruction::LShr: { uint32_t shiftAmt = C2V.getZExtValue(); if (shiftAmt < C1V.getBitWidth()) - return Context.getConstantInt(C1V.lshr(shiftAmt)); + return ConstantInt::get(Context, C1V.lshr(shiftAmt)); else return Context.getUndef(C1->getType()); // too big shift is undef } case Instruction::AShr: { uint32_t shiftAmt = C2V.getZExtValue(); if (shiftAmt < C1V.getBitWidth()) - return Context.getConstantInt(C1V.ashr(shiftAmt)); + return ConstantInt::get(Context, C1V.ashr(shiftAmt)); else return Context.getUndef(C1->getType()); // too big shift is undef } @@ -1420,25 +1420,25 @@ Constant *llvm::ConstantFoldCompareInstruction(LLVMContext &Context, switch (pred) { default: llvm_unreachable("Invalid ICmp Predicate"); return 0; case ICmpInst::ICMP_EQ: - return Context.getConstantInt(Type::Int1Ty, V1 == V2); + return ConstantInt::get(Type::Int1Ty, V1 == V2); case ICmpInst::ICMP_NE: - return Context.getConstantInt(Type::Int1Ty, V1 != V2); + return ConstantInt::get(Type::Int1Ty, V1 != V2); case ICmpInst::ICMP_SLT: - return Context.getConstantInt(Type::Int1Ty, V1.slt(V2)); + return ConstantInt::get(Type::Int1Ty, V1.slt(V2)); case ICmpInst::ICMP_SGT: - return Context.getConstantInt(Type::Int1Ty, V1.sgt(V2)); + return ConstantInt::get(Type::Int1Ty, V1.sgt(V2)); case ICmpInst::ICMP_SLE: - return Context.getConstantInt(Type::Int1Ty, V1.sle(V2)); + return ConstantInt::get(Type::Int1Ty, V1.sle(V2)); case ICmpInst::ICMP_SGE: - return Context.getConstantInt(Type::Int1Ty, V1.sge(V2)); + return ConstantInt::get(Type::Int1Ty, V1.sge(V2)); case ICmpInst::ICMP_ULT: - return Context.getConstantInt(Type::Int1Ty, V1.ult(V2)); + return ConstantInt::get(Type::Int1Ty, V1.ult(V2)); case ICmpInst::ICMP_UGT: - return Context.getConstantInt(Type::Int1Ty, V1.ugt(V2)); + return ConstantInt::get(Type::Int1Ty, V1.ugt(V2)); case ICmpInst::ICMP_ULE: - return Context.getConstantInt(Type::Int1Ty, V1.ule(V2)); + return ConstantInt::get(Type::Int1Ty, V1.ule(V2)); case ICmpInst::ICMP_UGE: - return Context.getConstantInt(Type::Int1Ty, V1.uge(V2)); + return ConstantInt::get(Type::Int1Ty, V1.uge(V2)); } } else if (isa<ConstantFP>(C1) && isa<ConstantFP>(C2)) { APFloat C1V = cast<ConstantFP>(C1)->getValueAPF(); @@ -1449,38 +1449,38 @@ Constant *llvm::ConstantFoldCompareInstruction(LLVMContext &Context, case FCmpInst::FCMP_FALSE: return Context.getFalse(); case FCmpInst::FCMP_TRUE: return Context.getTrue(); case FCmpInst::FCMP_UNO: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpUnordered); + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpUnordered); case FCmpInst::FCMP_ORD: - return Context.getConstantInt(Type::Int1Ty, R!=APFloat::cmpUnordered); + return ConstantInt::get(Type::Int1Ty, R!=APFloat::cmpUnordered); case FCmpInst::FCMP_UEQ: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpUnordered || + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpUnordered || R==APFloat::cmpEqual); case FCmpInst::FCMP_OEQ: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpEqual); + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpEqual); case FCmpInst::FCMP_UNE: - return Context.getConstantInt(Type::Int1Ty, R!=APFloat::cmpEqual); + return ConstantInt::get(Type::Int1Ty, R!=APFloat::cmpEqual); case FCmpInst::FCMP_ONE: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpLessThan || + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpLessThan || R==APFloat::cmpGreaterThan); case FCmpInst::FCMP_ULT: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpUnordered || + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpUnordered || R==APFloat::cmpLessThan); case FCmpInst::FCMP_OLT: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpLessThan); + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpLessThan); case FCmpInst::FCMP_UGT: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpUnordered || + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpUnordered || R==APFloat::cmpGreaterThan); case FCmpInst::FCMP_OGT: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpGreaterThan); + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpGreaterThan); case FCmpInst::FCMP_ULE: - return Context.getConstantInt(Type::Int1Ty, R!=APFloat::cmpGreaterThan); + return ConstantInt::get(Type::Int1Ty, R!=APFloat::cmpGreaterThan); case FCmpInst::FCMP_OLE: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpLessThan || + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpLessThan || R==APFloat::cmpEqual); case FCmpInst::FCMP_UGE: - return Context.getConstantInt(Type::Int1Ty, R!=APFloat::cmpLessThan); + return ConstantInt::get(Type::Int1Ty, R!=APFloat::cmpLessThan); case FCmpInst::FCMP_OGE: - return Context.getConstantInt(Type::Int1Ty, R==APFloat::cmpGreaterThan || + return ConstantInt::get(Type::Int1Ty, R==APFloat::cmpGreaterThan || R==APFloat::cmpEqual); } } else if (isa<VectorType>(C1->getType())) { @@ -1555,7 +1555,7 @@ Constant *llvm::ConstantFoldCompareInstruction(LLVMContext &Context, // If we evaluated the result, return it now. if (Result != -1) - return Context.getConstantInt(Type::Int1Ty, Result); + return ConstantInt::get(Type::Int1Ty, Result); } else { // Evaluate the relation between the two constants, per the predicate. @@ -1632,7 +1632,7 @@ Constant *llvm::ConstantFoldCompareInstruction(LLVMContext &Context, // If we evaluated the result, return it now. if (Result != -1) - return Context.getConstantInt(Type::Int1Ty, Result); + return ConstantInt::get(Type::Int1Ty, Result); if (!isa<ConstantExpr>(C1) && isa<ConstantExpr>(C2)) { // If C2 is a constant expr and C1 isn't, flip them around and fold the diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index f94cd9e..96f729a 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "LLVMContextImpl.h" #include "llvm/Constants.h" #include "ConstantFold.h" #include "llvm/DerivedTypes.h" @@ -171,6 +172,72 @@ ConstantInt::ConstantInt(const IntegerType *Ty, const APInt& V) assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type"); } +// Get a ConstantInt from an APInt. Note that the value stored in the DenseMap +// as the key, is a DenseMapAPIntKeyInfo::KeyTy which has provided the +// operator== and operator!= to ensure that the DenseMap doesn't attempt to +// compare APInt's of different widths, which would violate an APInt class +// invariant which generates an assertion. +ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt& V) { + // Get the corresponding integer type for the bit width of the value. + const IntegerType *ITy = Context.getIntegerType(V.getBitWidth()); + // get an existing value or the insertion position + DenseMapAPIntKeyInfo::KeyTy Key(V, ITy); + + Context.pImpl->ConstantsLock.reader_acquire(); + ConstantInt *&Slot = Context.pImpl->IntConstants[Key]; + Context.pImpl->ConstantsLock.reader_release(); + + if (!Slot) { + sys::SmartScopedWriter<true> Writer(Context.pImpl->ConstantsLock); + ConstantInt *&NewSlot = Context.pImpl->IntConstants[Key]; + if (!Slot) { + NewSlot = new ConstantInt(ITy, V); + } + + return NewSlot; + } else { + return Slot; + } +} + +Constant* ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) { + Constant *C = get(cast<IntegerType>(Ty->getScalarType()), + V, isSigned); + + // For vectors, broadcast the value. + if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) + return Ty->getContext().getConstantVector( + std::vector<Constant *>(VTy->getNumElements(), C)); + + return C; +} + +ConstantInt* ConstantInt::get(const IntegerType* Ty, uint64_t V, + bool isSigned) { + return get(Ty->getContext(), APInt(Ty->getBitWidth(), V, isSigned)); +} + +ConstantInt* ConstantInt::getSigned(const IntegerType* Ty, int64_t V) { + return get(Ty, V, true); +} + +Constant *ConstantInt::getSigned(const Type *Ty, int64_t V) { + return get(Ty, V, true); +} + +Constant* ConstantInt::get(const Type* Ty, const APInt& V) { + ConstantInt *C = get(Ty->getContext(), V); + assert(C->getType() == Ty->getScalarType() && + "ConstantInt type doesn't match the type implied by its value!"); + + // For vectors, broadcast the value. + if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) + return Ty->getContext().getConstantVector( + std::vector<Constant *>(VTy->getNumElements(), C)); + + return C; +} + //===----------------------------------------------------------------------===// // ConstantFP //===----------------------------------------------------------------------===// @@ -758,275 +825,6 @@ bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) { //===----------------------------------------------------------------------===// // Factory Function Implementation - -// The number of operands for each ConstantCreator::create method is -// determined by the ConstantTraits template. -// ConstantCreator - A class that is used to create constants by -// ValueMap*. This class should be partially specialized if there is -// something strange that needs to be done to interface to the ctor for the -// constant. -// -namespace llvm { - template<class ValType> - struct ConstantTraits; - - template<typename T, typename Alloc> - struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > { - static unsigned uses(const std::vector<T, Alloc>& v) { - return v.size(); - } - }; - - template<class ConstantClass, class TypeClass, class ValType> - struct VISIBILITY_HIDDEN ConstantCreator { - static ConstantClass *create(const TypeClass *Ty, const ValType &V) { - return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V); - } - }; - - template<class ConstantClass, class TypeClass> - struct VISIBILITY_HIDDEN ConvertConstantType { - static void convert(ConstantClass *OldC, const TypeClass *NewTy) { - llvm_unreachable("This type cannot be converted!"); - } - }; - - template<class ValType, class TypeClass, class ConstantClass, - bool HasLargeKey = false /*true for arrays and structs*/ > - class VISIBILITY_HIDDEN ValueMap : public AbstractTypeUser { - public: - typedef std::pair<const Type*, ValType> MapKey; - typedef std::map<MapKey, Constant *> MapTy; - typedef std::map<Constant*, typename MapTy::iterator> InverseMapTy; - typedef std::map<const Type*, typename MapTy::iterator> AbstractTypeMapTy; - private: - /// Map - This is the main map from the element descriptor to the Constants. - /// This is the primary way we avoid creating two of the same shape - /// constant. - MapTy Map; - - /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping - /// from the constants to their element in Map. This is important for - /// removal of constants from the array, which would otherwise have to scan - /// through the map with very large keys. - InverseMapTy InverseMap; - - /// AbstractTypeMap - Map for abstract type constants. - /// - AbstractTypeMapTy AbstractTypeMap; - - /// ValueMapLock - Mutex for this map. - sys::SmartMutex<true> ValueMapLock; - - public: - // NOTE: This function is not locked. It is the caller's responsibility - // to enforce proper synchronization. - typename MapTy::iterator map_end() { return Map.end(); } - - /// InsertOrGetItem - Return an iterator for the specified element. - /// If the element exists in the map, the returned iterator points to the - /// entry and Exists=true. If not, the iterator points to the newly - /// inserted entry and returns Exists=false. Newly inserted entries have - /// I->second == 0, and should be filled in. - /// NOTE: This function is not locked. It is the caller's responsibility - // to enforce proper synchronization. - typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, Constant *> - &InsertVal, - bool &Exists) { - std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal); - Exists = !IP.second; - return IP.first; - } - -private: - typename MapTy::iterator FindExistingElement(ConstantClass *CP) { - if (HasLargeKey) { - typename InverseMapTy::iterator IMI = InverseMap.find(CP); - assert(IMI != InverseMap.end() && IMI->second != Map.end() && - IMI->second->second == CP && - "InverseMap corrupt!"); - return IMI->second; - } - - typename MapTy::iterator I = - Map.find(MapKey(static_cast<const TypeClass*>(CP->getRawType()), - getValType(CP))); - if (I == Map.end() || I->second != CP) { - // FIXME: This should not use a linear scan. If this gets to be a - // performance problem, someone should look at this. - for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) - /* empty */; - } - return I; - } - - ConstantClass* Create(const TypeClass *Ty, const ValType &V, - typename MapTy::iterator I) { - ConstantClass* Result = - ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V); - - assert(Result->getType() == Ty && "Type specified is not correct!"); - I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.insert(std::make_pair(Result, I)); - - // If the type of the constant is abstract, make sure that an entry - // exists for it in the AbstractTypeMap. - if (Ty->isAbstract()) { - typename AbstractTypeMapTy::iterator TI = - AbstractTypeMap.find(Ty); - - if (TI == AbstractTypeMap.end()) { - // Add ourselves to the ATU list of the type. - cast<DerivedType>(Ty)->addAbstractTypeUser(this); - - AbstractTypeMap.insert(TI, std::make_pair(Ty, I)); - } - } - - return Result; - } -public: - - /// getOrCreate - Return the specified constant from the map, creating it if - /// necessary. - ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) { - sys::SmartScopedLock<true> Lock(ValueMapLock); - MapKey Lookup(Ty, V); - ConstantClass* Result = 0; - - typename MapTy::iterator I = Map.find(Lookup); - // Is it in the map? - if (I != Map.end()) - Result = static_cast<ConstantClass *>(I->second); - - if (!Result) { - // If no preexisting value, create one now... - Result = Create(Ty, V, I); - } - - return Result; - } - - void remove(ConstantClass *CP) { - sys::SmartScopedLock<true> Lock(ValueMapLock); - typename MapTy::iterator I = FindExistingElement(CP); - assert(I != Map.end() && "Constant not found in constant table!"); - assert(I->second == CP && "Didn't find correct element?"); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.erase(CP); - - // Now that we found the entry, make sure this isn't the entry that - // the AbstractTypeMap points to. - const TypeClass *Ty = static_cast<const TypeClass *>(I->first.first); - if (Ty->isAbstract()) { - assert(AbstractTypeMap.count(Ty) && - "Abstract type not in AbstractTypeMap?"); - typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty]; - if (ATMEntryIt == I) { - // Yes, we are removing the representative entry for this type. - // See if there are any other entries of the same type. - typename MapTy::iterator TmpIt = ATMEntryIt; - - // First check the entry before this one... - if (TmpIt != Map.begin()) { - --TmpIt; - if (TmpIt->first.first != Ty) // Not the same type, move back... - ++TmpIt; - } - - // If we didn't find the same type, try to move forward... - if (TmpIt == ATMEntryIt) { - ++TmpIt; - if (TmpIt == Map.end() || TmpIt->first.first != Ty) - --TmpIt; // No entry afterwards with the same type - } - - // If there is another entry in the map of the same abstract type, - // update the AbstractTypeMap entry now. - if (TmpIt != ATMEntryIt) { - ATMEntryIt = TmpIt; - } else { - // Otherwise, we are removing the last instance of this type - // from the table. Remove from the ATM, and from user list. - cast<DerivedType>(Ty)->removeAbstractTypeUser(this); - AbstractTypeMap.erase(Ty); - } - } - } - - Map.erase(I); - } - - - /// MoveConstantToNewSlot - If we are about to change C to be the element - /// specified by I, update our internal data structures to reflect this - /// fact. - /// NOTE: This function is not locked. It is the responsibility of the - /// caller to enforce proper synchronization if using this method. - void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) { - // First, remove the old location of the specified constant in the map. - typename MapTy::iterator OldI = FindExistingElement(C); - assert(OldI != Map.end() && "Constant not found in constant table!"); - assert(OldI->second == C && "Didn't find correct element?"); - - // If this constant is the representative element for its abstract type, - // update the AbstractTypeMap so that the representative element is I. - if (C->getType()->isAbstract()) { - typename AbstractTypeMapTy::iterator ATI = - AbstractTypeMap.find(C->getType()); - assert(ATI != AbstractTypeMap.end() && - "Abstract type not in AbstractTypeMap?"); - if (ATI->second == OldI) - ATI->second = I; - } - - // Remove the old entry from the map. - Map.erase(OldI); - - // Update the inverse map so that we know that this constant is now - // located at descriptor I. - if (HasLargeKey) { - assert(I->second == C && "Bad inversemap entry!"); - InverseMap[C] = I; - } - } - - void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { - sys::SmartScopedLock<true> Lock(ValueMapLock); - typename AbstractTypeMapTy::iterator I = - AbstractTypeMap.find(cast<Type>(OldTy)); - - assert(I != AbstractTypeMap.end() && - "Abstract type not in AbstractTypeMap?"); - - // Convert a constant at a time until the last one is gone. The last one - // leaving will remove() itself, causing the AbstractTypeMapEntry to be - // eliminated eventually. - do { - ConvertConstantType<ConstantClass, - TypeClass>::convert( - static_cast<ConstantClass *>(I->second->second), - cast<TypeClass>(NewTy)); - - I = AbstractTypeMap.find(cast<Type>(OldTy)); - } while (I != AbstractTypeMap.end()); - } - - // If the type became concrete without being refined to any other existing - // type, we just remove ourselves from the ATU list. - void typeBecameConcrete(const DerivedType *AbsTy) { - AbsTy->removeAbstractTypeUser(this); - } - - void dump() const { - DOUT << "Constant.cpp: ValueMap\n"; - } - }; -} - /// destroyConstant - Remove the constant from the constant table... /// void ConstantAggregateZero::destroyConstant() { diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index 55707b0..c35623e 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -365,8 +365,7 @@ LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty) { LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, int SignExtend) { - return wrap(getGlobalContext().getConstantInt(unwrap<IntegerType>(IntTy), N, - SignExtend != 0)); + return wrap(ConstantInt::get(unwrap<IntegerType>(IntTy), N, SignExtend != 0)); } static const fltSemantics &SemanticsForType(Type *Ty) { diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 5e5ce64..47cba01 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -704,7 +704,7 @@ void BranchInst::setSuccessorV(unsigned idx, BasicBlock *B) { static Value *getAISize(LLVMContext &Context, Value *Amt) { if (!Amt) - Amt = Context.getConstantInt(Type::Int32Ty, 1); + Amt = ConstantInt::get(Type::Int32Ty, 1); else { assert(!isa<BasicBlock>(Amt) && "Passed basic block into allocation size parameter! Use other ctor"); diff --git a/lib/VMCore/LLVMContext.cpp b/lib/VMCore/LLVMContext.cpp index d0f05eb..db81c61 100644 --- a/lib/VMCore/LLVMContext.cpp +++ b/lib/VMCore/LLVMContext.cpp @@ -39,7 +39,7 @@ static const uint64_t zero[2] = {0, 0}; Constant* LLVMContext::getNullValue(const Type* Ty) { switch (Ty->getTypeID()) { case Type::IntegerTyID: - return getConstantInt(Ty, 0); + return ConstantInt::get(Ty, 0); case Type::FloatTyID: return getConstantFP(APFloat(APInt(32, 0))); case Type::DoubleTyID: @@ -65,7 +65,7 @@ Constant* LLVMContext::getNullValue(const Type* Ty) { Constant* LLVMContext::getAllOnesValue(const Type* Ty) { if (const IntegerType* ITy = dyn_cast<IntegerType>(Ty)) - return getConstantInt(APInt::getAllOnesValue(ITy->getBitWidth())); + return ConstantInt::get(*this, APInt::getAllOnesValue(ITy->getBitWidth())); std::vector<Constant*> Elts; const VectorType* VTy = cast<VectorType>(Ty); @@ -92,51 +92,6 @@ ConstantInt* LLVMContext::getFalse() { return pImpl->getFalse(); } -Constant* LLVMContext::getConstantInt(const Type* Ty, uint64_t V, - bool isSigned) { - Constant *C = getConstantInt(cast<IntegerType>(Ty->getScalarType()), - V, isSigned); - - // For vectors, broadcast the value. - if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) - return - getConstantVector(std::vector<Constant *>(VTy->getNumElements(), C)); - - return C; -} - - -ConstantInt* LLVMContext::getConstantInt(const IntegerType* Ty, uint64_t V, - bool isSigned) { - return getConstantInt(APInt(Ty->getBitWidth(), V, isSigned)); -} - -ConstantInt* LLVMContext::getConstantIntSigned(const IntegerType* Ty, - int64_t V) { - return getConstantInt(Ty, V, true); -} - -Constant *LLVMContext::getConstantIntSigned(const Type *Ty, int64_t V) { - return getConstantInt(Ty, V, true); -} - -ConstantInt* LLVMContext::getConstantInt(const APInt& V) { - return pImpl->getConstantInt(V); -} - -Constant* LLVMContext::getConstantInt(const Type* Ty, const APInt& V) { - ConstantInt *C = getConstantInt(V); - assert(C->getType() == Ty->getScalarType() && - "ConstantInt type doesn't match the type implied by its value!"); - - // For vectors, broadcast the value. - if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) - return - getConstantVector(std::vector<Constant *>(VTy->getNumElements(), C)); - - return C; -} - // ConstantPointerNull accessors. ConstantPointerNull* LLVMContext::getConstantPointerNull(const PointerType* T) { return ConstantPointerNull::get(T); @@ -194,11 +149,11 @@ Constant* LLVMContext::getConstantArray(const std::string& Str, bool AddNull) { std::vector<Constant*> ElementVals; for (unsigned i = 0; i < Str.length(); ++i) - ElementVals.push_back(getConstantInt(Type::Int8Ty, Str[i])); + ElementVals.push_back(ConstantInt::get(Type::Int8Ty, Str[i])); // Add a null terminator to the string... if (AddNull) { - ElementVals.push_back(getConstantInt(Type::Int8Ty, 0)); + ElementVals.push_back(ConstantInt::get(Type::Int8Ty, 0)); } ArrayType *ATy = getArrayType(Type::Int8Ty, ElementVals.size()); @@ -302,8 +257,8 @@ Constant* LLVMContext::getConstantExprAlignOf(const Type* Ty) { // alignof is implemented as: (i64) gep ({i8,Ty}*)null, 0, 1 const Type *AligningTy = getStructType(Type::Int8Ty, Ty, NULL); Constant *NullPtr = getNullValue(AligningTy->getPointerTo()); - Constant *Zero = getConstantInt(Type::Int32Ty, 0); - Constant *One = getConstantInt(Type::Int32Ty, 1); + Constant *Zero = ConstantInt::get(Type::Int32Ty, 0); + Constant *One = ConstantInt::get(Type::Int32Ty, 1); Constant *Indices[2] = { Zero, One }; Constant *GEP = getConstantExprGetElementPtr(NullPtr, Indices, 2); return getConstantExprCast(Instruction::PtrToInt, GEP, Type::Int32Ty); @@ -463,7 +418,7 @@ Constant* LLVMContext::getConstantExprInsertValue(Constant* Agg, Constant* Val, Constant* LLVMContext::getConstantExprSizeOf(const Type* Ty) { // sizeof is implemented as: (i64) gep (Ty*)null, 1 - Constant *GEPIdx = getConstantInt(Type::Int32Ty, 1); + Constant *GEPIdx = ConstantInt::get(Type::Int32Ty, 1); Constant *GEP = getConstantExprGetElementPtr( getNullValue(getPointerTypeUnqual(Ty)), &GEPIdx, 1); return getConstantExprCast(Instruction::PtrToInt, GEP, Type::Int64Ty); diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index 34fc6e5..8e6c777 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -45,368 +45,10 @@ static std::vector<Constant*> getValType(ConstantVector *CP) { return Elements; } -namespace llvm { -template<typename T, typename Alloc> -struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > { - static unsigned uses(const std::vector<T, Alloc>& v) { - return v.size(); - } -}; - -template<class ConstantClass, class TypeClass, class ValType> -struct VISIBILITY_HIDDEN ConstantCreator { - static ConstantClass *create(const TypeClass *Ty, const ValType &V) { - return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V); - } -}; - -template<class ConstantClass, class TypeClass> -struct VISIBILITY_HIDDEN ConvertConstantType { - static void convert(ConstantClass *OldC, const TypeClass *NewTy) { - llvm_unreachable("This type cannot be converted!"); - } -}; - -// ConstantAggregateZero does not take extra "value" argument... -template<class ValType> -struct ConstantCreator<ConstantAggregateZero, Type, ValType> { - static ConstantAggregateZero *create(const Type *Ty, const ValType &V){ - return new ConstantAggregateZero(Ty); - } -}; - -template<> -struct ConvertConstantType<ConstantAggregateZero, Type> { - static void convert(ConstantAggregateZero *OldC, const Type *NewTy) { - // Make everyone now use a constant of the new type... - Constant *New = NewTy->getContext().getConstantAggregateZero(NewTy); - assert(New != OldC && "Didn't replace constant??"); - OldC->uncheckedReplaceAllUsesWith(New); - OldC->destroyConstant(); // This constant is now dead, destroy it. - } -}; - -template<> -struct ConvertConstantType<ConstantArray, ArrayType> { - static void convert(ConstantArray *OldC, const ArrayType *NewTy) { - // Make everyone now use a constant of the new type... - std::vector<Constant*> C; - for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) - C.push_back(cast<Constant>(OldC->getOperand(i))); - Constant *New = NewTy->getContext().getConstantArray(NewTy, C); - assert(New != OldC && "Didn't replace constant??"); - OldC->uncheckedReplaceAllUsesWith(New); - OldC->destroyConstant(); // This constant is now dead, destroy it. - } -}; - -template<> -struct ConvertConstantType<ConstantStruct, StructType> { - static void convert(ConstantStruct *OldC, const StructType *NewTy) { - // Make everyone now use a constant of the new type... - std::vector<Constant*> C; - for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) - C.push_back(cast<Constant>(OldC->getOperand(i))); - Constant *New = NewTy->getContext().getConstantStruct(NewTy, C); - assert(New != OldC && "Didn't replace constant??"); - - OldC->uncheckedReplaceAllUsesWith(New); - OldC->destroyConstant(); // This constant is now dead, destroy it. - } -}; - -template<> -struct ConvertConstantType<ConstantVector, VectorType> { - static void convert(ConstantVector *OldC, const VectorType *NewTy) { - // Make everyone now use a constant of the new type... - std::vector<Constant*> C; - for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) - C.push_back(cast<Constant>(OldC->getOperand(i))); - Constant *New = OldC->getContext().getConstantVector(NewTy, C); - assert(New != OldC && "Didn't replace constant??"); - OldC->uncheckedReplaceAllUsesWith(New); - OldC->destroyConstant(); // This constant is now dead, destroy it. - } -}; -} - -template<class ValType, class TypeClass, class ConstantClass, - bool HasLargeKey /*true for arrays and structs*/ > -class VISIBILITY_HIDDEN ValueMap : public AbstractTypeUser { -public: - typedef std::pair<const Type*, ValType> MapKey; - typedef std::map<MapKey, Constant *> MapTy; - typedef std::map<Constant*, typename MapTy::iterator> InverseMapTy; - typedef std::map<const Type*, typename MapTy::iterator> AbstractTypeMapTy; -private: - /// Map - This is the main map from the element descriptor to the Constants. - /// This is the primary way we avoid creating two of the same shape - /// constant. - MapTy Map; - - /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping - /// from the constants to their element in Map. This is important for - /// removal of constants from the array, which would otherwise have to scan - /// through the map with very large keys. - InverseMapTy InverseMap; - - /// AbstractTypeMap - Map for abstract type constants. - /// - AbstractTypeMapTy AbstractTypeMap; - - /// ValueMapLock - Mutex for this map. - sys::SmartMutex<true> ValueMapLock; - -public: - // NOTE: This function is not locked. It is the caller's responsibility - // to enforce proper synchronization. - typename MapTy::iterator map_end() { return Map.end(); } - - /// InsertOrGetItem - Return an iterator for the specified element. - /// If the element exists in the map, the returned iterator points to the - /// entry and Exists=true. If not, the iterator points to the newly - /// inserted entry and returns Exists=false. Newly inserted entries have - /// I->second == 0, and should be filled in. - /// NOTE: This function is not locked. It is the caller's responsibility - // to enforce proper synchronization. - typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, Constant *> - &InsertVal, - bool &Exists) { - std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal); - Exists = !IP.second; - return IP.first; - } - -private: - typename MapTy::iterator FindExistingElement(ConstantClass *CP) { - if (HasLargeKey) { - typename InverseMapTy::iterator IMI = InverseMap.find(CP); - assert(IMI != InverseMap.end() && IMI->second != Map.end() && - IMI->second->second == CP && - "InverseMap corrupt!"); - return IMI->second; - } - - typename MapTy::iterator I = - Map.find(MapKey(static_cast<const TypeClass*>(CP->getRawType()), - getValType(CP))); - if (I == Map.end() || I->second != CP) { - // FIXME: This should not use a linear scan. If this gets to be a - // performance problem, someone should look at this. - for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) - /* empty */; - } - return I; - } - - ConstantClass* Create(const TypeClass *Ty, const ValType &V, - typename MapTy::iterator I) { - ConstantClass* Result = - ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V); - - assert(Result->getType() == Ty && "Type specified is not correct!"); - I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.insert(std::make_pair(Result, I)); - - // If the type of the constant is abstract, make sure that an entry - // exists for it in the AbstractTypeMap. - if (Ty->isAbstract()) { - typename AbstractTypeMapTy::iterator TI = - AbstractTypeMap.find(Ty); - - if (TI == AbstractTypeMap.end()) { - // Add ourselves to the ATU list of the type. - cast<DerivedType>(Ty)->addAbstractTypeUser(this); - - AbstractTypeMap.insert(TI, std::make_pair(Ty, I)); - } - } - - return Result; - } -public: - - /// getOrCreate - Return the specified constant from the map, creating it if - /// necessary. - ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) { - sys::SmartScopedLock<true> Lock(ValueMapLock); - MapKey Lookup(Ty, V); - ConstantClass* Result = 0; - - typename MapTy::iterator I = Map.find(Lookup); - // Is it in the map? - if (I != Map.end()) - Result = static_cast<ConstantClass *>(I->second); - - if (!Result) { - // If no preexisting value, create one now... - Result = Create(Ty, V, I); - } - - return Result; - } - - void remove(ConstantClass *CP) { - sys::SmartScopedLock<true> Lock(ValueMapLock); - typename MapTy::iterator I = FindExistingElement(CP); - assert(I != Map.end() && "Constant not found in constant table!"); - assert(I->second == CP && "Didn't find correct element?"); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.erase(CP); - - // Now that we found the entry, make sure this isn't the entry that - // the AbstractTypeMap points to. - const TypeClass *Ty = static_cast<const TypeClass *>(I->first.first); - if (Ty->isAbstract()) { - assert(AbstractTypeMap.count(Ty) && - "Abstract type not in AbstractTypeMap?"); - typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty]; - if (ATMEntryIt == I) { - // Yes, we are removing the representative entry for this type. - // See if there are any other entries of the same type. - typename MapTy::iterator TmpIt = ATMEntryIt; - - // First check the entry before this one... - if (TmpIt != Map.begin()) { - --TmpIt; - if (TmpIt->first.first != Ty) // Not the same type, move back... - ++TmpIt; - } - - // If we didn't find the same type, try to move forward... - if (TmpIt == ATMEntryIt) { - ++TmpIt; - if (TmpIt == Map.end() || TmpIt->first.first != Ty) - --TmpIt; // No entry afterwards with the same type - } - - // If there is another entry in the map of the same abstract type, - // update the AbstractTypeMap entry now. - if (TmpIt != ATMEntryIt) { - ATMEntryIt = TmpIt; - } else { - // Otherwise, we are removing the last instance of this type - // from the table. Remove from the ATM, and from user list. - cast<DerivedType>(Ty)->removeAbstractTypeUser(this); - AbstractTypeMap.erase(Ty); - } - } - } - - Map.erase(I); - } - - - /// MoveConstantToNewSlot - If we are about to change C to be the element - /// specified by I, update our internal data structures to reflect this - /// fact. - /// NOTE: This function is not locked. It is the responsibility of the - /// caller to enforce proper synchronization if using this method. - void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) { - // First, remove the old location of the specified constant in the map. - typename MapTy::iterator OldI = FindExistingElement(C); - assert(OldI != Map.end() && "Constant not found in constant table!"); - assert(OldI->second == C && "Didn't find correct element?"); - - // If this constant is the representative element for its abstract type, - // update the AbstractTypeMap so that the representative element is I. - if (C->getType()->isAbstract()) { - typename AbstractTypeMapTy::iterator ATI = - AbstractTypeMap.find(C->getType()); - assert(ATI != AbstractTypeMap.end() && - "Abstract type not in AbstractTypeMap?"); - if (ATI->second == OldI) - ATI->second = I; - } - - // Remove the old entry from the map. - Map.erase(OldI); - - // Update the inverse map so that we know that this constant is now - // located at descriptor I. - if (HasLargeKey) { - assert(I->second == C && "Bad inversemap entry!"); - InverseMap[C] = I; - } - } - - void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { - sys::SmartScopedLock<true> Lock(ValueMapLock); - typename AbstractTypeMapTy::iterator I = - AbstractTypeMap.find(cast<Type>(OldTy)); - - assert(I != AbstractTypeMap.end() && - "Abstract type not in AbstractTypeMap?"); - - // Convert a constant at a time until the last one is gone. The last one - // leaving will remove() itself, causing the AbstractTypeMapEntry to be - // eliminated eventually. - do { - ConvertConstantType<ConstantClass, - TypeClass>::convert( - static_cast<ConstantClass *>(I->second->second), - cast<TypeClass>(NewTy)); - - I = AbstractTypeMap.find(cast<Type>(OldTy)); - } while (I != AbstractTypeMap.end()); - } - - // If the type became concrete without being refined to any other existing - // type, we just remove ourselves from the ATU list. - void typeBecameConcrete(const DerivedType *AbsTy) { - AbsTy->removeAbstractTypeUser(this); - } - - void dump() const { - DOUT << "Constant.cpp: ValueMap\n"; - } -}; LLVMContextImpl::LLVMContextImpl(LLVMContext &C) : - Context(C), TheTrueVal(0), TheFalseVal(0) { - AggZeroConstants = new ValueMap<char, Type, ConstantAggregateZero>(); - ArrayConstants = new ArrayConstantsTy(); - StructConstants = new StructConstantsTy(); - VectorConstants = new VectorConstantsTy(); -} + Context(C), TheTrueVal(0), TheFalseVal(0) { } -LLVMContextImpl::~LLVMContextImpl() { - delete AggZeroConstants; - delete ArrayConstants; - delete StructConstants; - delete VectorConstants; -} - -// Get a ConstantInt from an APInt. Note that the value stored in the DenseMap -// as the key, is a DenseMapAPIntKeyInfo::KeyTy which has provided the -// operator== and operator!= to ensure that the DenseMap doesn't attempt to -// compare APInt's of different widths, which would violate an APInt class -// invariant which generates an assertion. -ConstantInt *LLVMContextImpl::getConstantInt(const APInt& V) { - // Get the corresponding integer type for the bit width of the value. - const IntegerType *ITy = Context.getIntegerType(V.getBitWidth()); - // get an existing value or the insertion position - DenseMapAPIntKeyInfo::KeyTy Key(V, ITy); - - ConstantsLock.reader_acquire(); - ConstantInt *&Slot = IntConstants[Key]; - ConstantsLock.reader_release(); - - if (!Slot) { - sys::SmartScopedWriter<true> Writer(ConstantsLock); - ConstantInt *&NewSlot = IntConstants[Key]; - if (!Slot) { - NewSlot = new ConstantInt(ITy, V); - } - - return NewSlot; - } else { - return Slot; - } -} ConstantFP *LLVMContextImpl::getConstantFP(const APFloat &V) { DenseMapAPFloatKeyInfo::KeyTy Key(V); @@ -483,7 +125,7 @@ LLVMContextImpl::getConstantAggregateZero(const Type *Ty) { "Cannot create an aggregate zero of non-aggregate type!"); // Implicitly locked. - return AggZeroConstants->getOrCreate(Ty, 0); + return AggZeroConstants.getOrCreate(Ty, 0); } Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty, @@ -493,12 +135,12 @@ Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty, Constant *C = V[0]; if (!C->isNullValue()) { // Implicitly locked. - return ArrayConstants->getOrCreate(Ty, V); + return ArrayConstants.getOrCreate(Ty, V); } for (unsigned i = 1, e = V.size(); i != e; ++i) if (V[i] != C) { // Implicitly locked. - return ArrayConstants->getOrCreate(Ty, V); + return ArrayConstants.getOrCreate(Ty, V); } } @@ -511,7 +153,7 @@ Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty, for (unsigned i = 0, e = V.size(); i != e; ++i) if (!V[i]->isNullValue()) // Implicitly locked. - return StructConstants->getOrCreate(Ty, V); + return StructConstants.getOrCreate(Ty, V); return Context.getConstantAggregateZero(Ty); } @@ -539,7 +181,7 @@ Constant *LLVMContextImpl::getConstantVector(const VectorType *Ty, return Context.getUndef(Ty); // Implicitly locked. - return VectorConstants->getOrCreate(Ty, V); + return VectorConstants.getOrCreate(Ty, V); } // *** erase methods *** @@ -556,19 +198,19 @@ void LLVMContextImpl::erase(MDNode *M) { } void LLVMContextImpl::erase(ConstantAggregateZero *Z) { - AggZeroConstants->remove(Z); + AggZeroConstants.remove(Z); } void LLVMContextImpl::erase(ConstantArray *C) { - ArrayConstants->remove(C); + ArrayConstants.remove(C); } void LLVMContextImpl::erase(ConstantStruct *S) { - StructConstants->remove(S); + StructConstants.remove(S); } void LLVMContextImpl::erase(ConstantVector *V) { - VectorConstants->remove(V); + VectorConstants.remove(V); } // *** RAUW helpers *** @@ -621,7 +263,7 @@ Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, sys::SmartScopedWriter<true> Writer(ConstantsLock); bool Exists; ArrayConstantsTy::MapTy::iterator I = - ArrayConstants->InsertOrGetItem(Lookup, Exists); + ArrayConstants.InsertOrGetItem(Lookup, Exists); if (Exists) { Replacement = I->second; @@ -630,7 +272,7 @@ Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, // creating a new constant array, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! - ArrayConstants->MoveConstantToNewSlot(CA, I); + ArrayConstants.MoveConstantToNewSlot(CA, I); // Update to the new value. Optimize for the case when we have a single // operand that we're changing, but handle bulk updates efficiently. @@ -693,7 +335,7 @@ Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS, sys::SmartScopedWriter<true> Writer(ConstantsLock); bool Exists; StructConstantsTy::MapTy::iterator I = - StructConstants->InsertOrGetItem(Lookup, Exists); + StructConstants.InsertOrGetItem(Lookup, Exists); if (Exists) { Replacement = I->second; @@ -702,7 +344,7 @@ Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS, // creating a new constant struct, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! - StructConstants->MoveConstantToNewSlot(CS, I); + StructConstants.MoveConstantToNewSlot(CS, I); // Update to the new value. CS->setOperand(OperandToUpdate, ToC); diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index 7351624..96ac0f8 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -16,6 +16,7 @@ #define LLVM_LLVMCONTEXT_IMPL_H #include "llvm/LLVMContext.h" +#include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -29,14 +30,336 @@ #include <map> #include <vector> -template<class ValType, class TypeClass, class ConstantClass, - bool HasLargeKey = false /*true for arrays and structs*/ > -class ValueMap; - namespace llvm { template<class ValType> struct ConstantTraits; +// The number of operands for each ConstantCreator::create method is +// determined by the ConstantTraits template. +// ConstantCreator - A class that is used to create constants by +// ValueMap*. This class should be partially specialized if there is +// something strange that needs to be done to interface to the ctor for the +// constant. +// +template<typename T, typename Alloc> +struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > { + static unsigned uses(const std::vector<T, Alloc>& v) { + return v.size(); + } +}; + +template<class ConstantClass, class TypeClass, class ValType> +struct VISIBILITY_HIDDEN ConstantCreator { + static ConstantClass *create(const TypeClass *Ty, const ValType &V) { + return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V); + } +}; + +template<class ConstantClass, class TypeClass> +struct VISIBILITY_HIDDEN ConvertConstantType { + static void convert(ConstantClass *OldC, const TypeClass *NewTy) { + llvm_unreachable("This type cannot be converted!"); + } +}; + +// ConstantAggregateZero does not take extra "value" argument... +template<class ValType> +struct ConstantCreator<ConstantAggregateZero, Type, ValType> { + static ConstantAggregateZero *create(const Type *Ty, const ValType &V){ + return new ConstantAggregateZero(Ty); + } +}; + +template<> +struct ConvertConstantType<ConstantAggregateZero, Type> { + static void convert(ConstantAggregateZero *OldC, const Type *NewTy) { + // Make everyone now use a constant of the new type... + Constant *New = NewTy->getContext().getConstantAggregateZero(NewTy); + assert(New != OldC && "Didn't replace constant??"); + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } +}; + +template<> +struct ConvertConstantType<ConstantArray, ArrayType> { + static void convert(ConstantArray *OldC, const ArrayType *NewTy) { + // Make everyone now use a constant of the new type... + std::vector<Constant*> C; + for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) + C.push_back(cast<Constant>(OldC->getOperand(i))); + Constant *New = NewTy->getContext().getConstantArray(NewTy, C); + assert(New != OldC && "Didn't replace constant??"); + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } +}; + +template<> +struct ConvertConstantType<ConstantStruct, StructType> { + static void convert(ConstantStruct *OldC, const StructType *NewTy) { + // Make everyone now use a constant of the new type... + std::vector<Constant*> C; + for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) + C.push_back(cast<Constant>(OldC->getOperand(i))); + Constant *New = NewTy->getContext().getConstantStruct(NewTy, C); + assert(New != OldC && "Didn't replace constant??"); + + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } +}; + +template<> +struct ConvertConstantType<ConstantVector, VectorType> { + static void convert(ConstantVector *OldC, const VectorType *NewTy) { + // Make everyone now use a constant of the new type... + std::vector<Constant*> C; + for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) + C.push_back(cast<Constant>(OldC->getOperand(i))); + Constant *New = OldC->getContext().getConstantVector(NewTy, C); + assert(New != OldC && "Didn't replace constant??"); + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } +}; + +template<class ValType, class TypeClass, class ConstantClass, + bool HasLargeKey = false /*true for arrays and structs*/ > +class ValueMap : public AbstractTypeUser { +public: + typedef std::pair<const Type*, ValType> MapKey; + typedef std::map<MapKey, Constant *> MapTy; + typedef std::map<Constant*, typename MapTy::iterator> InverseMapTy; + typedef std::map<const Type*, typename MapTy::iterator> AbstractTypeMapTy; +private: + /// Map - This is the main map from the element descriptor to the Constants. + /// This is the primary way we avoid creating two of the same shape + /// constant. + MapTy Map; + + /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping + /// from the constants to their element in Map. This is important for + /// removal of constants from the array, which would otherwise have to scan + /// through the map with very large keys. + InverseMapTy InverseMap; + + /// AbstractTypeMap - Map for abstract type constants. + /// + AbstractTypeMapTy AbstractTypeMap; + + /// ValueMapLock - Mutex for this map. + sys::SmartMutex<true> ValueMapLock; + +public: + // NOTE: This function is not locked. It is the caller's responsibility + // to enforce proper synchronization. + typename MapTy::iterator map_end() { return Map.end(); } + + /// InsertOrGetItem - Return an iterator for the specified element. + /// If the element exists in the map, the returned iterator points to the + /// entry and Exists=true. If not, the iterator points to the newly + /// inserted entry and returns Exists=false. Newly inserted entries have + /// I->second == 0, and should be filled in. + /// NOTE: This function is not locked. It is the caller's responsibility + // to enforce proper synchronization. + typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, Constant *> + &InsertVal, + bool &Exists) { + std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal); + Exists = !IP.second; + return IP.first; + } + +private: + typename MapTy::iterator FindExistingElement(ConstantClass *CP) { + if (HasLargeKey) { + typename InverseMapTy::iterator IMI = InverseMap.find(CP); + assert(IMI != InverseMap.end() && IMI->second != Map.end() && + IMI->second->second == CP && + "InverseMap corrupt!"); + return IMI->second; + } + + typename MapTy::iterator I = + Map.find(MapKey(static_cast<const TypeClass*>(CP->getRawType()), + getValType(CP))); + if (I == Map.end() || I->second != CP) { + // FIXME: This should not use a linear scan. If this gets to be a + // performance problem, someone should look at this. + for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) + /* empty */; + } + return I; + } + + ConstantClass* Create(const TypeClass *Ty, const ValType &V, + typename MapTy::iterator I) { + ConstantClass* Result = + ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V); + + assert(Result->getType() == Ty && "Type specified is not correct!"); + I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); + + if (HasLargeKey) // Remember the reverse mapping if needed. + InverseMap.insert(std::make_pair(Result, I)); + + // If the type of the constant is abstract, make sure that an entry + // exists for it in the AbstractTypeMap. + if (Ty->isAbstract()) { + typename AbstractTypeMapTy::iterator TI = + AbstractTypeMap.find(Ty); + + if (TI == AbstractTypeMap.end()) { + // Add ourselves to the ATU list of the type. + cast<DerivedType>(Ty)->addAbstractTypeUser(this); + + AbstractTypeMap.insert(TI, std::make_pair(Ty, I)); + } + } + + return Result; + } +public: + + /// getOrCreate - Return the specified constant from the map, creating it if + /// necessary. + ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) { + sys::SmartScopedLock<true> Lock(ValueMapLock); + MapKey Lookup(Ty, V); + ConstantClass* Result = 0; + + typename MapTy::iterator I = Map.find(Lookup); + // Is it in the map? + if (I != Map.end()) + Result = static_cast<ConstantClass *>(I->second); + + if (!Result) { + // If no preexisting value, create one now... + Result = Create(Ty, V, I); + } + + return Result; + } + + void remove(ConstantClass *CP) { + sys::SmartScopedLock<true> Lock(ValueMapLock); + typename MapTy::iterator I = FindExistingElement(CP); + assert(I != Map.end() && "Constant not found in constant table!"); + assert(I->second == CP && "Didn't find correct element?"); + + if (HasLargeKey) // Remember the reverse mapping if needed. + InverseMap.erase(CP); + + // Now that we found the entry, make sure this isn't the entry that + // the AbstractTypeMap points to. + const TypeClass *Ty = static_cast<const TypeClass *>(I->first.first); + if (Ty->isAbstract()) { + assert(AbstractTypeMap.count(Ty) && + "Abstract type not in AbstractTypeMap?"); + typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty]; + if (ATMEntryIt == I) { + // Yes, we are removing the representative entry for this type. + // See if there are any other entries of the same type. + typename MapTy::iterator TmpIt = ATMEntryIt; + + // First check the entry before this one... + if (TmpIt != Map.begin()) { + --TmpIt; + if (TmpIt->first.first != Ty) // Not the same type, move back... + ++TmpIt; + } + + // If we didn't find the same type, try to move forward... + if (TmpIt == ATMEntryIt) { + ++TmpIt; + if (TmpIt == Map.end() || TmpIt->first.first != Ty) + --TmpIt; // No entry afterwards with the same type + } + + // If there is another entry in the map of the same abstract type, + // update the AbstractTypeMap entry now. + if (TmpIt != ATMEntryIt) { + ATMEntryIt = TmpIt; + } else { + // Otherwise, we are removing the last instance of this type + // from the table. Remove from the ATM, and from user list. + cast<DerivedType>(Ty)->removeAbstractTypeUser(this); + AbstractTypeMap.erase(Ty); + } + } + } + + Map.erase(I); + } + + + /// MoveConstantToNewSlot - If we are about to change C to be the element + /// specified by I, update our internal data structures to reflect this + /// fact. + /// NOTE: This function is not locked. It is the responsibility of the + /// caller to enforce proper synchronization if using this method. + void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) { + // First, remove the old location of the specified constant in the map. + typename MapTy::iterator OldI = FindExistingElement(C); + assert(OldI != Map.end() && "Constant not found in constant table!"); + assert(OldI->second == C && "Didn't find correct element?"); + + // If this constant is the representative element for its abstract type, + // update the AbstractTypeMap so that the representative element is I. + if (C->getType()->isAbstract()) { + typename AbstractTypeMapTy::iterator ATI = + AbstractTypeMap.find(C->getType()); + assert(ATI != AbstractTypeMap.end() && + "Abstract type not in AbstractTypeMap?"); + if (ATI->second == OldI) + ATI->second = I; + } + + // Remove the old entry from the map. + Map.erase(OldI); + + // Update the inverse map so that we know that this constant is now + // located at descriptor I. + if (HasLargeKey) { + assert(I->second == C && "Bad inversemap entry!"); + InverseMap[C] = I; + } + } + + void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { + sys::SmartScopedLock<true> Lock(ValueMapLock); + typename AbstractTypeMapTy::iterator I = + AbstractTypeMap.find(cast<Type>(OldTy)); + + assert(I != AbstractTypeMap.end() && + "Abstract type not in AbstractTypeMap?"); + + // Convert a constant at a time until the last one is gone. The last one + // leaving will remove() itself, causing the AbstractTypeMapEntry to be + // eliminated eventually. + do { + ConvertConstantType<ConstantClass, + TypeClass>::convert( + static_cast<ConstantClass *>(I->second->second), + cast<TypeClass>(NewTy)); + + I = AbstractTypeMap.find(cast<Type>(OldTy)); + } while (I != AbstractTypeMap.end()); + } + + // If the type became concrete without being refined to any other existing + // type, we just remove ourselves from the ATU list. + void typeBecameConcrete(const DerivedType *AbsTy) { + AbsTy->removeAbstractTypeUser(this); + } + + void dump() const { + DOUT << "Constant.cpp: ValueMap\n"; + } +}; + + class ConstantInt; class ConstantFP; class MDString; @@ -112,19 +435,19 @@ class LLVMContextImpl { FoldingSet<MDNode> MDNodeSet; - ValueMap<char, Type, ConstantAggregateZero> *AggZeroConstants; + ValueMap<char, Type, ConstantAggregateZero> AggZeroConstants; typedef ValueMap<std::vector<Constant*>, ArrayType, ConstantArray, true /*largekey*/> ArrayConstantsTy; - ArrayConstantsTy *ArrayConstants; + ArrayConstantsTy ArrayConstants; typedef ValueMap<std::vector<Constant*>, StructType, ConstantStruct, true /*largekey*/> StructConstantsTy; - StructConstantsTy *StructConstants; + StructConstantsTy StructConstants; typedef ValueMap<std::vector<Constant*>, VectorType, ConstantVector> VectorConstantsTy; - VectorConstantsTy *VectorConstants; + VectorConstantsTy VectorConstants; LLVMContext &Context; ConstantInt *TheTrueVal; @@ -132,13 +455,10 @@ class LLVMContextImpl { LLVMContextImpl(); LLVMContextImpl(const LLVMContextImpl&); + + friend class ConstantInt; public: LLVMContextImpl(LLVMContext &C); - ~LLVMContextImpl(); - - /// Return a ConstantInt with the specified value and an implied Type. The - /// type is the integer type that corresponds to the bit width of the value. - ConstantInt *getConstantInt(const APInt &V); ConstantFP *getConstantFP(const APFloat &V); @@ -161,14 +481,14 @@ public: if (TheTrueVal) return TheTrueVal; else - return (TheTrueVal = Context.getConstantInt(IntegerType::get(1), 1)); + return (TheTrueVal = ConstantInt::get(IntegerType::get(1), 1)); } ConstantInt *getFalse() { if (TheFalseVal) return TheFalseVal; else - return (TheFalseVal = Context.getConstantInt(IntegerType::get(1), 0)); + return (TheFalseVal = ConstantInt::get(IntegerType::get(1), 0)); } void erase(MDString *M); |