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 | |
parent | eea723fe02edba0a1215fa235ba425ae93202dc9 (diff) | |
download | external_llvm-18c7f80b3e83ab584bd8572695a3cde8bafd9d3c.zip external_llvm-18c7f80b3e83ab584bd8572695a3cde8bafd9d3c.tar.gz external_llvm-18c7f80b3e83ab584bd8572695a3cde8bafd9d3c.tar.bz2 |
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')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 29 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 196 | ||||
-rw-r--r-- | lib/VMCore/Core.cpp | 4 | ||||
-rw-r--r-- | lib/VMCore/IRBuilder.cpp | 2 |
4 files changed, 104 insertions, 127 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 3815777..7bec783 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -827,30 +827,21 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) { - // As a special case, print the array as a string if it is an array of - // i8 with ConstantInt values. - // Type *ETy = CA->getType()->getElementType(); - if (CA->isString()) { - Out << "c\""; - PrintEscapedString(CA->getAsString(), Out); - Out << '"'; - } else { // Cannot output in string format... - Out << '['; + Out << '['; + TypePrinter.print(ETy, Out); + Out << ' '; + WriteAsOperandInternal(Out, CA->getOperand(0), + &TypePrinter, Machine, + Context); + for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { + Out << ", "; TypePrinter.print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CA->getOperand(0), - &TypePrinter, Machine, + WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine, Context); - for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { - Out << ", "; - TypePrinter.print(ETy, Out); - Out << ' '; - WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine, - Context); - } - Out << ']'; } + Out << ']'; return; } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index f7884c6..7d423c0 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... // diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index ea4e952..c376546 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -634,8 +634,8 @@ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, LLVMBool DontNullTerminate) { /* Inverted the sense of AddNull because ', 0)' is a better mnemonic for null termination than ', 1)'. */ - return wrap(ConstantArray::get(*unwrap(C), StringRef(Str, Length), - DontNullTerminate == 0)); + return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), + DontNullTerminate == 0)); } LLVMValueRef LLVMConstStructInContext(LLVMContextRef C, LLVMValueRef *ConstantVals, diff --git a/lib/VMCore/IRBuilder.cpp b/lib/VMCore/IRBuilder.cpp index 0994394..b459234 100644 --- a/lib/VMCore/IRBuilder.cpp +++ b/lib/VMCore/IRBuilder.cpp @@ -24,7 +24,7 @@ using namespace llvm; /// specified. If Name is specified, it is the name of the global variable /// created. Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) { - Constant *StrConstant = ConstantArray::get(Context, Str, true); + Constant *StrConstant = ConstantDataArray::getString(Context, Str); Module &M = *BB->getParent()->getParent(); GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), true, GlobalValue::PrivateLinkage, |