X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FConstants.cpp;h=28b7e45bf55fa2b3db57bfd088d1ffeff7859430;hb=5c4cd0d82e22a50e95a1acffa3364e4f7658ab32;hp=58fe8882c8afd4e1c74881657301c873d138ac0c;hpb=e0e769607c8d6569daea0ff55a99fa2532029342;p=oota-llvm.git diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 58fe8882c8a..28b7e45bf55 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Constants.h" -#include "ConstantFolding.h" +#include "ConstantFold.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalValue.h" #include "llvm/Instructions.h" @@ -22,6 +22,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MathExtras.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include #include @@ -89,14 +90,32 @@ bool Constant::canTrap() const { } } +/// ContaintsRelocations - Return true if the constant value contains +/// relocations which cannot be resolved at compile time. +bool Constant::ContainsRelocations() const { + if (isa(this)) + return true; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i)->ContainsRelocations()) + return true; + return false; +} + // Static constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(const Type *Ty) { + static uint64_t zero[2] = {0, 0}; switch (Ty->getTypeID()) { case Type::IntegerTyID: return ConstantInt::get(Ty, 0); case Type::FloatTyID: + return ConstantFP::get(Ty, APFloat(APInt(32, 0))); case Type::DoubleTyID: - return ConstantFP::get(Ty, 0.0); + return ConstantFP::get(Ty, APFloat(APInt(64, 0))); + case Type::X86_FP80TyID: + return ConstantFP::get(Ty, APFloat(APInt(80, 2, zero))); + case Type::FP128TyID: + case Type::PPC_FP128TyID: + return ConstantFP::get(Ty, APFloat(APInt(128, 2, zero))); case Type::PointerTyID: return ConstantPointerNull::get(cast(Ty)); case Type::StructTyID: @@ -110,50 +129,211 @@ Constant *Constant::getNullValue(const Type *Ty) { } } +Constant *Constant::getAllOnesValue(const Type *Ty) { + if (const IntegerType* ITy = dyn_cast(Ty)) + return ConstantInt::get(APInt::getAllOnesValue(ITy->getBitWidth())); + return ConstantVector::getAllOnesValue(cast(Ty)); +} // Static constructor to create an integral constant with all bits set ConstantInt *ConstantInt::getAllOnesValue(const Type *Ty) { if (const IntegerType* ITy = dyn_cast(Ty)) - if (ITy->getBitWidth() == 1) - return ConstantInt::getTrue(); - else - return ConstantInt::get(Ty, int64_t(-1)); + return ConstantInt::get(APInt::getAllOnesValue(ITy->getBitWidth())); return 0; } -/// @returns the value for an packed integer constant of the given type that +/// @returns the value for a vector integer constant of the given type that /// has all its bits set to true. /// @brief Get the all ones value ConstantVector *ConstantVector::getAllOnesValue(const VectorType *Ty) { std::vector Elts; Elts.resize(Ty->getNumElements(), ConstantInt::getAllOnesValue(Ty->getElementType())); - assert(Elts[0] && "Not a packed integer type!"); + assert(Elts[0] && "Not a vector integer type!"); return cast(ConstantVector::get(Elts)); } //===----------------------------------------------------------------------===// -// ConstantXXX Classes +// ConstantInt //===----------------------------------------------------------------------===// +ConstantInt::ConstantInt(const IntegerType *Ty, const APInt& V) + : Constant(Ty, ConstantIntVal, 0, 0), Val(V) { + assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type"); +} + +ConstantInt *ConstantInt::TheTrueVal = 0; +ConstantInt *ConstantInt::TheFalseVal = 0; + +namespace llvm { + void CleanupTrueFalse(void *) { + ConstantInt::ResetTrueFalse(); + } +} + +static ManagedCleanup TrueFalseCleanup; + +ConstantInt *ConstantInt::CreateTrueFalseVals(bool WhichOne) { + assert(TheTrueVal == 0 && TheFalseVal == 0); + TheTrueVal = get(Type::Int1Ty, 1); + TheFalseVal = get(Type::Int1Ty, 0); + + // Ensure that llvm_shutdown nulls out TheTrueVal/TheFalseVal. + TrueFalseCleanup.Register(); + + return WhichOne ? TheTrueVal : TheFalseVal; +} + + +namespace { + struct DenseMapAPIntKeyInfo { + struct KeyTy { + APInt val; + const Type* type; + KeyTy(const APInt& V, const Type* Ty) : val(V), type(Ty) {} + KeyTy(const KeyTy& that) : val(that.val), type(that.type) {} + bool operator==(const KeyTy& that) const { + return type == that.type && this->val == that.val; + } + bool operator!=(const KeyTy& that) const { + return !this->operator==(that); + } + }; + static inline KeyTy getEmptyKey() { return KeyTy(APInt(1,0), 0); } + static inline KeyTy getTombstoneKey() { return KeyTy(APInt(1,1), 0); } + static unsigned getHashValue(const KeyTy &Key) { + return DenseMapInfo::getHashValue(Key.type) ^ + Key.val.getHashValue(); + } + static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { + return LHS == RHS; + } + static bool isPod() { return false; } + }; +} + + +typedef DenseMap IntMapTy; +static ManagedStatic IntConstants; + +ConstantInt *ConstantInt::get(const Type *Ty, uint64_t V, bool isSigned) { + const IntegerType *ITy = cast(Ty); + return get(APInt(ITy->getBitWidth(), V, isSigned)); +} + +// Get a ConstantInt from an APInt. Note that the value stored in the DenseMap +// as the key, is a DensMapAPIntKeyInfo::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(const APInt& V) { + // Get the corresponding integer type for the bit width of the value. + const IntegerType *ITy = IntegerType::get(V.getBitWidth()); + // get an existing value or the insertion position + DenseMapAPIntKeyInfo::KeyTy Key(V, ITy); + ConstantInt *&Slot = (*IntConstants)[Key]; + // if it exists, return it. + if (Slot) + return Slot; + // otherwise create a new one, insert it, and return it. + return Slot = new ConstantInt(ITy, V); +} + +//===----------------------------------------------------------------------===// +// ConstantFP //===----------------------------------------------------------------------===// -// Normal Constructors -ConstantInt::ConstantInt(bool V) - : Constant(Type::Int1Ty, ConstantIntVal, 0, 0), Val(uint64_t(V)) { +ConstantFP::ConstantFP(const Type *Ty, const APFloat& V) + : Constant(Ty, ConstantFPVal, 0, 0), Val(V) { + // temporary + if (Ty==Type::FloatTy) + assert(&V.getSemantics()==&APFloat::IEEEsingle); + else if (Ty==Type::DoubleTy) + assert(&V.getSemantics()==&APFloat::IEEEdouble); + else if (Ty==Type::X86_FP80Ty) + assert(&V.getSemantics()==&APFloat::x87DoubleExtended); + else if (Ty==Type::FP128Ty) + assert(&V.getSemantics()==&APFloat::IEEEquad); + else + assert(0); +} + +bool ConstantFP::isNullValue() const { + return Val.isZero() && !Val.isNegative(); +} + +ConstantFP *ConstantFP::getNegativeZero(const Type *Ty) { + APFloat apf = cast (Constant::getNullValue(Ty))->getValueAPF(); + apf.changeSign(); + return ConstantFP::get(Ty, apf); } -ConstantInt::ConstantInt(const Type *Ty, uint64_t V) - : Constant(Ty, ConstantIntVal, 0, 0), Val(Ty == Type::Int1Ty ? bool(V) : V) { +bool ConstantFP::isExactlyValue(const APFloat& V) const { + return Val.bitwiseIsEqual(V); } -ConstantFP::ConstantFP(const Type *Ty, double V) - : Constant(Ty, ConstantFPVal, 0, 0) { - assert(isValueValidForType(Ty, V) && "Value too large for type!"); - Val = V; +namespace { + struct DenseMapAPFloatKeyInfo { + struct KeyTy { + APFloat val; + KeyTy(const APFloat& V) : val(V){} + KeyTy(const KeyTy& that) : val(that.val) {} + bool operator==(const KeyTy& that) const { + return this->val.bitwiseIsEqual(that.val); + } + bool operator!=(const KeyTy& that) const { + return !this->operator==(that); + } + }; + static inline KeyTy getEmptyKey() { + return KeyTy(APFloat(APFloat::Bogus,1)); + } + static inline KeyTy getTombstoneKey() { + return KeyTy(APFloat(APFloat::Bogus,2)); + } + static unsigned getHashValue(const KeyTy &Key) { + return Key.val.getHashValue(); + } + static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { + return LHS == RHS; + } + static bool isPod() { return false; } + }; } +//---- ConstantFP::get() implementation... +// +typedef DenseMap FPMapTy; + +static ManagedStatic FPConstants; + +ConstantFP *ConstantFP::get(const Type *Ty, const APFloat& V) { + // temporary + if (Ty==Type::FloatTy) + assert(&V.getSemantics()==&APFloat::IEEEsingle); + else if (Ty==Type::DoubleTy) + assert(&V.getSemantics()==&APFloat::IEEEdouble); + else if (Ty==Type::X86_FP80Ty) + assert(&V.getSemantics()==&APFloat::x87DoubleExtended); + else if (Ty==Type::FP128Ty) + assert(&V.getSemantics()==&APFloat::IEEEquad); + else + assert(0); + + DenseMapAPFloatKeyInfo::KeyTy Key(V); + ConstantFP *&Slot = (*FPConstants)[Key]; + if (Slot) return Slot; + return Slot = new ConstantFP(Ty, V); +} + +//===----------------------------------------------------------------------===// +// ConstantXXX Classes +//===----------------------------------------------------------------------===// + + ConstantArray::ConstantArray(const ArrayType *T, const std::vector &V) : Constant(T, ConstantArrayVal, new Use[V.size()], V.size()) { @@ -209,7 +389,7 @@ ConstantVector::ConstantVector(const VectorType *T, assert((C->getType() == T->getElementType() || (T->isAbstract() && C->getType()->getTypeID() == T->getElementType()->getTypeID())) && - "Initializer for packed element doesn't match packed element type!"); + "Initializer for vector element doesn't match vector element type!"); OL->init(C, this); } } @@ -542,15 +722,31 @@ bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) { return (Val >= Min && Val <= Max); } -bool ConstantFP::isValueValidForType(const Type *Ty, double Val) { +bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) { + // convert modifies in place, so make a copy. + APFloat Val2 = APFloat(Val); switch (Ty->getTypeID()) { default: return false; // These can't be represented as floating point! - // TODO: Figure out how to test if a double can be cast to a float! + // FIXME rounding mode needs to be more flexible case Type::FloatTyID: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) == + APFloat::opOK; case Type::DoubleTyID: - return true; // This is the largest type... + return &Val2.getSemantics() == &APFloat::IEEEsingle || + &Val2.getSemantics() == &APFloat::IEEEdouble || + Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven) == + APFloat::opOK; + case Type::X86_FP80TyID: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + &Val2.getSemantics() == &APFloat::IEEEdouble || + &Val2.getSemantics() == &APFloat::x87DoubleExtended; + case Type::FP128TyID: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + &Val2.getSemantics() == &APFloat::IEEEdouble || + &Val2.getSemantics() == &APFloat::IEEEquad; } } @@ -602,15 +798,6 @@ namespace llvm { /// AbstractTypeMapTy AbstractTypeMap; - private: - void clear(std::vector &Constants) { - for(typename MapTy::iterator I = Map.begin(); I != Map.end(); ++I) - Constants.push_back(I->second); - Map.clear(); - AbstractTypeMap.clear(); - InverseMap.clear(); - } - public: typename MapTy::iterator map_end() { return Map.end(); } @@ -800,64 +987,6 @@ public: } -//---- ConstantInt::get() implementations... -// -static ManagedStatic > IntConstants; - -// Get a ConstantInt from an int64_t. Note here that we canoncialize the value -// to a uint64_t value that has been zero extended down to the size of the -// integer type of the ConstantInt. This allows the getZExtValue method to -// just return the stored value while getSExtValue has to convert back to sign -// extended. getZExtValue is more common in LLVM than getSExtValue(). -ConstantInt *ConstantInt::get(const Type *Ty, int64_t V) { - if (Ty == Type::Int1Ty) - if (V & 1) - return getTrue(); - else - return getFalse(); - return IntConstants->getOrCreate(Ty, V & cast(Ty)->getBitMask()); -} - -//---- ConstantFP::get() implementation... -// -namespace llvm { - template<> - struct ConstantCreator { - static ConstantFP *create(const Type *Ty, uint64_t V) { - assert(Ty == Type::DoubleTy); - return new ConstantFP(Ty, BitsToDouble(V)); - } - }; - template<> - struct ConstantCreator { - static ConstantFP *create(const Type *Ty, uint32_t V) { - assert(Ty == Type::FloatTy); - return new ConstantFP(Ty, BitsToFloat(V)); - } - }; -} - -static ManagedStatic > DoubleConstants; -static ManagedStatic > FloatConstants; - -bool ConstantFP::isNullValue() const { - return DoubleToBits(Val) == 0; -} - -bool ConstantFP::isExactlyValue(double V) const { - return DoubleToBits(V) == DoubleToBits(Val); -} - - -ConstantFP *ConstantFP::get(const Type *Ty, double V) { - if (Ty == Type::FloatTy) { - // Force the value through memory to normalize it. - return FloatConstants->getOrCreate(Ty, FloatToBits(V)); - } else { - assert(Ty == Type::DoubleTy); - return DoubleConstants->getOrCreate(Ty, DoubleToBits(V)); - } -} //---- ConstantAggregateZero::get() implementation... // @@ -1108,7 +1237,7 @@ static ManagedStatic, VectorType, Constant *ConstantVector::get(const VectorType *Ty, const std::vector &V) { - // If this is an all-zero packed, return a ConstantAggregateZero object + // If this is an all-zero vector, return a ConstantAggregateZero object if (!V.empty()) { Constant *C = V[0]; if (!C->isNullValue()) @@ -1132,7 +1261,7 @@ void ConstantVector::destroyConstant() { destroyConstantImpl(); } -/// This function will return true iff every element in this packed constant +/// This function will return true iff every element in this vector constant /// is set to all ones. /// @returns true iff this constant's emements are all set to all ones. /// @brief Determine if the value is all ones. @@ -1675,7 +1804,7 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C, Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C, Value* const *Idxs, unsigned NumIdx) { - assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs, NumIdx, true) && + assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx, true) && "GEP indices invalid!"); if (Constant *FC = ConstantFoldGetElementPtr(C, (Constant**)Idxs, NumIdx)) @@ -1697,7 +1826,7 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs, unsigned NumIdx) { // Get the result type of the getelementptr! const Type *Ty = - GetElementPtrInst::getIndexedType(C->getType(), Idxs, NumIdx, true); + GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx, true); assert(Ty && "GEP indices invalid!"); return getGetElementPtrTy(PointerType::get(Ty), C, Idxs, NumIdx); } @@ -1810,12 +1939,12 @@ Constant *ConstantExpr::getZeroValueForNegationExpr(const Type *Ty) { if (const VectorType *PTy = dyn_cast(Ty)) if (PTy->getElementType()->isFloatingPoint()) { std::vector zeros(PTy->getNumElements(), - ConstantFP::get(PTy->getElementType(),-0.0)); + ConstantFP::getNegativeZero(PTy->getElementType())); return ConstantVector::get(PTy, zeros); } - if (Ty->isFloatingPoint()) - return ConstantFP::get(Ty, -0.0); + if (Ty->isFloatingPoint()) + return ConstantFP::getNegativeZero(Ty); return Constant::getNullValue(Ty); } @@ -1834,14 +1963,21 @@ const char *ConstantExpr::getOpcodeName() const { //===----------------------------------------------------------------------===// // replaceUsesOfWithOnConstant implementations +/// replaceUsesOfWithOnConstant - Update this constant array to change uses of +/// 'From' to be uses of 'To'. This must update the uniquing data structures +/// etc. +/// +/// Note that we intentionally replace all uses of From with To here. Consider +/// a large array that uses 'From' 1000 times. By handling this case all here, +/// ConstantArray::replaceUsesOfWithOnConstant is only invoked once, and that +/// single invocation handles all 1000 uses. Handling them one at a time would +/// work, but would be really slow because it would have to unique each updated +/// array instance. void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); - unsigned OperandToUpdate = U-OperandList; - assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); - std::pair Lookup; Lookup.first.first = getType(); Lookup.second = this; @@ -1852,18 +1988,28 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, // Fill values with the modified operands of the constant array. Also, // compute whether this turns into an all-zeros array. bool isAllZeros = false; + unsigned NumUpdated = 0; if (!ToC->isNullValue()) { - for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) - Values.push_back(cast(O->get())); + for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { + Constant *Val = cast(O->get()); + if (Val == From) { + Val = ToC; + ++NumUpdated; + } + Values.push_back(Val); + } } else { isAllZeros = true; for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { Constant *Val = cast(O->get()); + if (Val == From) { + Val = ToC; + ++NumUpdated; + } Values.push_back(Val); if (isAllZeros) isAllZeros = Val->isNullValue(); } } - Values[OperandToUpdate] = ToC; Constant *Replacement = 0; if (isAllZeros) { @@ -1883,8 +2029,18 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, // in place! ArrayConstants->MoveConstantToNewSlot(this, I); - // Update to the new value. - setOperand(OperandToUpdate, ToC); + // Update to the new value. Optimize for the case when we have a single + // operand that we're changing, but handle bulk updates efficiently. + if (NumUpdated == 1) { + unsigned OperandToUpdate = U-OperandList; + assert(getOperand(OperandToUpdate) == From && + "ReplaceAllUsesWith broken!"); + setOperand(OperandToUpdate, ToC); + } else { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i) == From) + setOperand(i, ToC); + } return; } }