diff options
author | Chris Lattner <sabre@nondot.org> | 2012-02-05 02:29:43 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2012-02-05 02:29:43 +0000 |
commit | 18c7f80b3e83ab584bd8572695a3cde8bafd9d3c (patch) | |
tree | 93b57cd1b5fb8fa1e48c06e4bef7571f02603243 /lib/VMCore/Constants.cpp | |
parent | eea723fe02edba0a1215fa235ba425ae93202dc9 (diff) | |
download | llvm-18c7f80b3e83ab584bd8572695a3cde8bafd9d3c.tar.gz llvm-18c7f80b3e83ab584bd8572695a3cde8bafd9d3c.tar.bz2 llvm-18c7f80b3e83ab584bd8572695a3cde8bafd9d3c.tar.xz |
reapply the patches reverted in r149470 that reenable ConstantDataArray,
but with a critical fix to the SelectionDAG code that optimizes copies
from strings into immediate stores: the previous code was stopping reading
string data at the first nul. Address this by adding a new argument to
llvm::getConstantStringInfo, preserving the behavior before the patch.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149800 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore/Constants.cpp')
-rw-r--r-- | lib/VMCore/Constants.cpp | 196 |
1 files changed, 91 insertions, 105 deletions
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index f7884c6862..7d423c04a6 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -176,7 +176,7 @@ Constant *Constant::getAggregateElement(unsigned Elt) const { return UV->getElementValue(Elt); if (const ConstantDataSequential *CDS =dyn_cast<ConstantDataSequential>(this)) - return CDS->getElementAsConstant(Elt); + return Elt < CDS->getNumElements() ? CDS->getElementAsConstant(Elt) : 0; return 0; } @@ -666,6 +666,13 @@ UndefValue *UndefValue::getElementValue(unsigned Idx) const { // ConstantXXX Classes //===----------------------------------------------------------------------===// +template <typename ItTy, typename EltTy> +static bool rangeOnlyContains(ItTy Start, ItTy End, EltTy Elt) { + for (; Start != End; ++Start) + if (*Start != Elt) + return false; + return true; +} ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V) : Constant(T, ConstantArrayVal, @@ -680,54 +687,97 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V) } Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { + // Empty arrays are canonicalized to ConstantAggregateZero. + if (V.empty()) + return ConstantAggregateZero::get(Ty); + for (unsigned i = 0, e = V.size(); i != e; ++i) { assert(V[i]->getType() == Ty->getElementType() && "Wrong type in array element initializer"); } LLVMContextImpl *pImpl = Ty->getContext().pImpl; - // If this is an all-zero array, return a ConstantAggregateZero object - bool isAllZero = true; - bool isUndef = false; - if (!V.empty()) { - Constant *C = V[0]; - isAllZero = C->isNullValue(); - isUndef = isa<UndefValue>(C); - - if (isAllZero || isUndef) - for (unsigned i = 1, e = V.size(); i != e; ++i) - if (V[i] != C) { - isAllZero = false; - isUndef = false; - break; - } - } - - if (isAllZero) - return ConstantAggregateZero::get(Ty); - if (isUndef) + + // If this is an all-zero array, return a ConstantAggregateZero object. If + // all undef, return an UndefValue, if "all simple", then return a + // ConstantDataArray. + Constant *C = V[0]; + if (isa<UndefValue>(C) && rangeOnlyContains(V.begin(), V.end(), C)) return UndefValue::get(Ty); - return pImpl->ArrayConstants.getOrCreate(Ty, V); -} -/// ConstantArray::get(const string&) - Return an array that is initialized to -/// contain the specified string. If length is zero then a null terminator is -/// added to the specified string so that it may be used in a natural way. -/// Otherwise, the length parameter specifies how much of the string to use -/// and it won't be null terminated. -/// -Constant *ConstantArray::get(LLVMContext &Context, StringRef Str, - bool AddNull) { - SmallVector<Constant*, 8> ElementVals; - ElementVals.reserve(Str.size() + size_t(AddNull)); - for (unsigned i = 0; i < Str.size(); ++i) - ElementVals.push_back(ConstantInt::get(Type::getInt8Ty(Context), Str[i])); + if (C->isNullValue() && rangeOnlyContains(V.begin(), V.end(), C)) + return ConstantAggregateZero::get(Ty); - // Add a null terminator to the string... - if (AddNull) - ElementVals.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0)); + // Check to see if all of the elements are ConstantFP or ConstantInt and if + // the element type is compatible with ConstantDataVector. If so, use it. + if (ConstantDataSequential::isElementTypeCompatible(C->getType())) { + // We speculatively build the elements here even if it turns out that there + // is a constantexpr or something else weird in the array, since it is so + // uncommon for that to happen. + if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) { + if (CI->getType()->isIntegerTy(8)) { + SmallVector<uint8_t, 16> Elts; + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) + Elts.push_back(CI->getZExtValue()); + else + break; + if (Elts.size() == V.size()) + return ConstantDataArray::get(C->getContext(), Elts); + } else if (CI->getType()->isIntegerTy(16)) { + SmallVector<uint16_t, 16> Elts; + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) + Elts.push_back(CI->getZExtValue()); + else + break; + if (Elts.size() == V.size()) + return ConstantDataArray::get(C->getContext(), Elts); + } else if (CI->getType()->isIntegerTy(32)) { + SmallVector<uint32_t, 16> Elts; + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) + Elts.push_back(CI->getZExtValue()); + else + break; + if (Elts.size() == V.size()) + return ConstantDataArray::get(C->getContext(), Elts); + } else if (CI->getType()->isIntegerTy(64)) { + SmallVector<uint64_t, 16> Elts; + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) + Elts.push_back(CI->getZExtValue()); + else + break; + if (Elts.size() == V.size()) + return ConstantDataArray::get(C->getContext(), Elts); + } + } + + if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { + if (CFP->getType()->isFloatTy()) { + SmallVector<float, 16> Elts; + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) + Elts.push_back(CFP->getValueAPF().convertToFloat()); + else + break; + if (Elts.size() == V.size()) + return ConstantDataArray::get(C->getContext(), Elts); + } else if (CFP->getType()->isDoubleTy()) { + SmallVector<double, 16> Elts; + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) + Elts.push_back(CFP->getValueAPF().convertToDouble()); + else + break; + if (Elts.size() == V.size()) + return ConstantDataArray::get(C->getContext(), Elts); + } + } + } - ArrayType *ATy = ArrayType::get(Type::getInt8Ty(Context), ElementVals.size()); - return get(ATy, ElementVals); + // Otherwise, we really do want to create a ConstantArray. + return pImpl->ArrayConstants.getOrCreate(Ty, V); } /// getTypeForElements - Return an anonymous struct type to use for a constant @@ -839,8 +889,7 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) { // Check to see if all of the elements are ConstantFP or ConstantInt and if // the element type is compatible with ConstantDataVector. If so, use it. - if (ConstantDataSequential::isElementTypeCompatible(C->getType()) && - (isa<ConstantFP>(C) || isa<ConstantInt>(C))) { + if (ConstantDataSequential::isElementTypeCompatible(C->getType())) { // We speculatively build the elements here even if it turns out that there // is a constantexpr or something else weird in the array, since it is so // uncommon for that to happen. @@ -1146,69 +1195,6 @@ void ConstantArray::destroyConstant() { destroyConstantImpl(); } -/// isString - This method returns true if the array is an array of i8, and -/// if the elements of the array are all ConstantInt's. -bool ConstantArray::isString() const { - // Check the element type for i8... - if (!getType()->getElementType()->isIntegerTy(8)) - return false; - // Check the elements to make sure they are all integers, not constant - // expressions. - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (!isa<ConstantInt>(getOperand(i))) - return false; - return true; -} - -/// isCString - This method returns true if the array is a string (see -/// isString) and it ends in a null byte \\0 and does not contains any other -/// null bytes except its terminator. -bool ConstantArray::isCString() const { - // Check the element type for i8... - if (!getType()->getElementType()->isIntegerTy(8)) - return false; - - // Last element must be a null. - if (!getOperand(getNumOperands()-1)->isNullValue()) - return false; - // Other elements must be non-null integers. - for (unsigned i = 0, e = getNumOperands()-1; i != e; ++i) { - if (!isa<ConstantInt>(getOperand(i))) - return false; - if (getOperand(i)->isNullValue()) - return false; - } - return true; -} - - -/// convertToString - Helper function for getAsString() and getAsCString(). -static std::string convertToString(const User *U, unsigned len) { - std::string Result; - Result.reserve(len); - for (unsigned i = 0; i != len; ++i) - Result.push_back((char)cast<ConstantInt>(U->getOperand(i))->getZExtValue()); - return Result; -} - -/// getAsString - If this array is isString(), then this method converts the -/// array to an std::string and returns it. Otherwise, it asserts out. -/// -std::string ConstantArray::getAsString() const { - assert(isString() && "Not a string!"); - return convertToString(this, getNumOperands()); -} - - -/// getAsCString - If this array is isCString(), then this method converts the -/// array (without the trailing null byte) to an std::string and returns it. -/// Otherwise, it asserts out. -/// -std::string ConstantArray::getAsCString() const { - assert(isCString() && "Not a string!"); - return convertToString(this, getNumOperands() - 1); -} - //---- ConstantStruct::get() implementation... // |