mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-26 05:25:47 +00:00
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:
@@ -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...
|
||||
//
|
||||
|
Reference in New Issue
Block a user