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
This commit is contained in:
Chris Lattner
2012-02-05 02:29:43 +00:00
parent eea723fe02
commit 18c7f80b3e
19 changed files with 276 additions and 539 deletions

View File

@@ -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,56 +687,99 @@ 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 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);
if (isAllZero || isUndef)
for (unsigned i = 1, e = V.size(); i != e; ++i)
if (V[i] != C) {
isAllZero = false;
isUndef = false;
break;
}
if (C->isNullValue() && rangeOnlyContains(V.begin(), V.end(), C))
return ConstantAggregateZero::get(Ty);
// 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);
}
}
}
if (isAllZero)
return ConstantAggregateZero::get(Ty);
if (isUndef)
return UndefValue::get(Ty);
// Otherwise, we really do want to create a ConstantArray.
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]));
// Add a null terminator to the string...
if (AddNull)
ElementVals.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0));
ArrayType *ATy = ArrayType::get(Type::getInt8Ty(Context), ElementVals.size());
return get(ATy, ElementVals);
}
/// getTypeForElements - Return an anonymous struct type to use for a constant
/// with the specified set of elements. The list must not be empty.
StructType *ConstantStruct::getTypeForElements(LLVMContext &Context,
@@ -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...
//