summaryrefslogtreecommitdiff
path: root/lib/VMCore/Constants.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2012-02-05 02:29:43 +0000
committerChris Lattner <sabre@nondot.org>2012-02-05 02:29:43 +0000
commit18c7f80b3e83ab584bd8572695a3cde8bafd9d3c (patch)
tree93b57cd1b5fb8fa1e48c06e4bef7571f02603243 /lib/VMCore/Constants.cpp
parenteea723fe02edba0a1215fa235ba425ae93202dc9 (diff)
downloadllvm-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.cpp196
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...
//