mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-15 23:57:48 +00:00
Change ConstantArray::get to form a ConstantDataArray when possible,
kicking in the big win of ConstantDataArray. As part of this, change the implementation of GetConstantStringInfo in ValueTracking to work with ConstantDataArray (and not ConstantArray) making it dramatically, amazingly, more efficient in the process and renaming it to getConstantStringInfo. This keeps around a GetConstantStringInfo entrypoint that (grossly) forwards to getConstantStringInfo and constructs the std::string required, but existing clients should move over to getConstantStringInfo instead. llvm-svn: 149351
This commit is contained in:
parent
b4d65d2788
commit
b463bd21fc
@ -17,14 +17,13 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class Value;
|
||||
class Instruction;
|
||||
class APInt;
|
||||
class TargetData;
|
||||
class StringRef;
|
||||
|
||||
/// ComputeMaskedBits - Determine which of the bits specified in Mask are
|
||||
/// known to be either zero or one and return them in the KnownZero/KnownOne
|
||||
@ -125,16 +124,17 @@ namespace llvm {
|
||||
return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD);
|
||||
}
|
||||
|
||||
/// GetConstantStringInfo - This function computes the length of a
|
||||
/// getConstantStringInfo - This function computes the length of a
|
||||
/// null-terminated C string pointed to by V. If successful, it returns true
|
||||
/// and returns the string in Str. If unsuccessful, it returns false. If
|
||||
/// StopAtNul is set to true (the default), the returned string is truncated
|
||||
/// by a nul character in the global. If StopAtNul is false, the nul
|
||||
/// character is included in the result string.
|
||||
/// and returns the string in Str. If unsuccessful, it returns false. This
|
||||
/// does not include the trailing nul character.
|
||||
bool getConstantStringInfo(const Value *V, StringRef &Str,
|
||||
uint64_t Offset = 0);
|
||||
|
||||
// FIXME: Remove this.
|
||||
bool GetConstantStringInfo(const Value *V, std::string &Str,
|
||||
uint64_t Offset = 0,
|
||||
bool StopAtNul = true);
|
||||
|
||||
uint64_t Offset = 0);
|
||||
|
||||
/// GetStringLength - If we can compute the length of the string pointed to by
|
||||
/// the specified pointer, return 'len+1'. If we can't, return 0.
|
||||
uint64_t GetStringLength(Value *V);
|
||||
|
@ -476,9 +476,9 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C,
|
||||
|
||||
// Instead of loading constant c string, use corresponding integer value
|
||||
// directly if string length is small enough.
|
||||
std::string Str;
|
||||
if (TD && GetConstantStringInfo(CE, Str) && !Str.empty()) {
|
||||
unsigned StrLen = Str.length();
|
||||
StringRef Str;
|
||||
if (TD && getConstantStringInfo(CE, Str) && !Str.empty()) {
|
||||
unsigned StrLen = Str.size();
|
||||
Type *Ty = cast<PointerType>(CE->getType())->getElementType();
|
||||
unsigned NumBits = Ty->getPrimitiveSizeInBits();
|
||||
// Replace load with immediate integer if the result is an integer or fp
|
||||
|
@ -1369,25 +1369,21 @@ Value *llvm::isBytewiseValue(Value *V) {
|
||||
}
|
||||
}
|
||||
|
||||
// A ConstantArray is splatable if all its members are equal and also
|
||||
// splatable.
|
||||
if (ConstantArray *CA = dyn_cast<ConstantArray>(V)) {
|
||||
if (CA->getNumOperands() == 0)
|
||||
return 0;
|
||||
|
||||
Value *Val = isBytewiseValue(CA->getOperand(0));
|
||||
// A ConstantDataArray/Vector is splatable if all its members are equal and
|
||||
// also splatable.
|
||||
if (ConstantDataSequential *CA = dyn_cast<ConstantDataSequential>(V)) {
|
||||
Value *Elt = CA->getElementAsConstant(0);
|
||||
Value *Val = isBytewiseValue(Elt);
|
||||
if (!Val)
|
||||
return 0;
|
||||
|
||||
for (unsigned I = 1, E = CA->getNumOperands(); I != E; ++I)
|
||||
if (CA->getOperand(I-1) != CA->getOperand(I))
|
||||
for (unsigned I = 1, E = CA->getNumElements(); I != E; ++I)
|
||||
if (CA->getElementAsConstant(I) != Elt)
|
||||
return 0;
|
||||
|
||||
return Val;
|
||||
}
|
||||
|
||||
// FIXME: Vector types (e.g., <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>).
|
||||
|
||||
// Conceptually, we could handle things like:
|
||||
// %a = zext i8 %X to i16
|
||||
// %b = shl i16 %a, 8
|
||||
@ -1607,33 +1603,29 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
|
||||
}
|
||||
|
||||
|
||||
/// GetConstantStringInfo - This function computes the length of a
|
||||
// FIXME: Remove this.
|
||||
bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
|
||||
uint64_t Offset) {
|
||||
StringRef Tmp;
|
||||
if (!getConstantStringInfo(V, Tmp, Offset))
|
||||
return false;
|
||||
Str = Tmp.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// getConstantStringInfo - This function computes the length of a
|
||||
/// null-terminated C string pointed to by V. If successful, it returns true
|
||||
/// and returns the string in Str. If unsuccessful, it returns false.
|
||||
bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
|
||||
uint64_t Offset, bool StopAtNul) {
|
||||
// If V is NULL then return false;
|
||||
if (V == NULL) return false;
|
||||
bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
|
||||
uint64_t Offset) {
|
||||
assert(V);
|
||||
|
||||
// Look through bitcast instructions.
|
||||
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(V))
|
||||
return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul);
|
||||
// Look through bitcast instructions and geps.
|
||||
V = V->stripPointerCasts();
|
||||
|
||||
// If the value is not a GEP instruction nor a constant expression with a
|
||||
// GEP instruction, then return false because ConstantArray can't occur
|
||||
// any other way.
|
||||
const User *GEP = 0;
|
||||
if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) {
|
||||
GEP = GEPI;
|
||||
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
||||
if (CE->getOpcode() == Instruction::BitCast)
|
||||
return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul);
|
||||
if (CE->getOpcode() != Instruction::GetElementPtr)
|
||||
return false;
|
||||
GEP = CE;
|
||||
}
|
||||
|
||||
if (GEP) {
|
||||
// If the value is a GEP instructionor constant expression, treat it as an
|
||||
// offset.
|
||||
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
||||
// Make sure the GEP has exactly three arguments.
|
||||
if (GEP->getNumOperands() != 3)
|
||||
return false;
|
||||
@ -1658,51 +1650,45 @@ bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
|
||||
StartIdx = CI->getZExtValue();
|
||||
else
|
||||
return false;
|
||||
return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset,
|
||||
StopAtNul);
|
||||
return getConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset);
|
||||
}
|
||||
|
||||
// The GEP instruction, constant or instruction, must reference a global
|
||||
// variable that is a constant and is initialized. The referenced constant
|
||||
// initializer is the array that we'll use for optimization.
|
||||
const GlobalVariable* GV = dyn_cast<GlobalVariable>(V);
|
||||
const GlobalVariable *GV = dyn_cast<GlobalVariable>(V);
|
||||
if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer())
|
||||
return false;
|
||||
const Constant *GlobalInit = GV->getInitializer();
|
||||
|
||||
|
||||
// Handle the all-zeros case
|
||||
if (GlobalInit->isNullValue()) {
|
||||
if (GV->getInitializer()->isNullValue()) {
|
||||
// This is a degenerate case. The initializer is constant zero so the
|
||||
// length of the string must be zero.
|
||||
Str.clear();
|
||||
Str = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be a Constant Array
|
||||
const ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit);
|
||||
if (Array == 0 || !Array->getType()->getElementType()->isIntegerTy(8))
|
||||
const ConstantDataArray *Array =
|
||||
dyn_cast<ConstantDataArray>(GV->getInitializer());
|
||||
if (Array == 0 || !Array->isString())
|
||||
return false;
|
||||
|
||||
// Get the number of elements in the array
|
||||
uint64_t NumElts = Array->getType()->getNumElements();
|
||||
|
||||
uint64_t NumElts = Array->getType()->getArrayNumElements();
|
||||
|
||||
// Start out with the entire array in the StringRef.
|
||||
Str = Array->getAsString();
|
||||
|
||||
if (Offset > NumElts)
|
||||
return false;
|
||||
|
||||
// Traverse the constant array from 'Offset' which is the place the GEP refers
|
||||
// to in the array.
|
||||
Str.reserve(NumElts-Offset);
|
||||
for (unsigned i = Offset; i != NumElts; ++i) {
|
||||
const Constant *Elt = Array->getOperand(i);
|
||||
const ConstantInt *CI = dyn_cast<ConstantInt>(Elt);
|
||||
if (!CI) // This array isn't suitable, non-int initializer.
|
||||
return false;
|
||||
if (StopAtNul && CI->isZero())
|
||||
return true; // we found end of string, success!
|
||||
Str += (char)CI->getZExtValue();
|
||||
}
|
||||
|
||||
// The array isn't null terminated, but maybe this is a memcpy, not a strcpy.
|
||||
// Skip over 'offset' bytes.
|
||||
Str = Str.substr(Offset);
|
||||
// Trim off the \0 and anything after it. If the array is not nul terminated,
|
||||
// we just return the whole end of string. The client may know some other way
|
||||
// that the string is length-bound.
|
||||
Str = Str.substr(0, Str.find('\0'));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1714,8 +1700,7 @@ bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
|
||||
/// the specified pointer, return 'len+1'. If we can't, return 0.
|
||||
static uint64_t GetStringLengthH(Value *V, SmallPtrSet<PHINode*, 32> &PHIs) {
|
||||
// Look through noop bitcast instructions.
|
||||
if (BitCastInst *BCI = dyn_cast<BitCastInst>(V))
|
||||
return GetStringLengthH(BCI->getOperand(0), PHIs);
|
||||
V = V->stripPointerCasts();
|
||||
|
||||
// If this is a PHI node, there are two cases: either we have already seen it
|
||||
// or we haven't.
|
||||
@ -1751,83 +1736,13 @@ static uint64_t GetStringLengthH(Value *V, SmallPtrSet<PHINode*, 32> &PHIs) {
|
||||
if (Len1 != Len2) return 0;
|
||||
return Len1;
|
||||
}
|
||||
|
||||
// As a special-case, "@string = constant i8 0" is also a string with zero
|
||||
// length, not wrapped in a bitcast or GEP.
|
||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
|
||||
if (GV->isConstant() && GV->hasDefinitiveInitializer())
|
||||
if (GV->getInitializer()->isNullValue()) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the value is not a GEP instruction nor a constant expression with a
|
||||
// GEP instruction, then return unknown.
|
||||
User *GEP = 0;
|
||||
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) {
|
||||
GEP = GEPI;
|
||||
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
||||
if (CE->getOpcode() != Instruction::GetElementPtr)
|
||||
return 0;
|
||||
GEP = CE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure the GEP has exactly three arguments.
|
||||
if (GEP->getNumOperands() != 3)
|
||||
|
||||
// Otherwise, see if we can read the string.
|
||||
StringRef StrData;
|
||||
if (!getConstantStringInfo(V, StrData))
|
||||
return 0;
|
||||
|
||||
// Check to make sure that the first operand of the GEP is an integer and
|
||||
// has value 0 so that we are sure we're indexing into the initializer.
|
||||
if (ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
|
||||
if (!Idx->isZero())
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
// If the second index isn't a ConstantInt, then this is a variable index
|
||||
// into the array. If this occurs, we can't say anything meaningful about
|
||||
// the string.
|
||||
uint64_t StartIdx = 0;
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(2)))
|
||||
StartIdx = CI->getZExtValue();
|
||||
else
|
||||
return 0;
|
||||
|
||||
// The GEP instruction, constant or instruction, must reference a global
|
||||
// variable that is a constant and is initialized. The referenced constant
|
||||
// initializer is the array that we'll use for optimization.
|
||||
GlobalVariable* GV = dyn_cast<GlobalVariable>(GEP->getOperand(0));
|
||||
if (!GV || !GV->isConstant() || !GV->hasInitializer() ||
|
||||
GV->mayBeOverridden())
|
||||
return 0;
|
||||
Constant *GlobalInit = GV->getInitializer();
|
||||
|
||||
// Handle the ConstantAggregateZero case, which is a degenerate case. The
|
||||
// initializer is constant zero so the length of the string must be zero.
|
||||
if (isa<ConstantAggregateZero>(GlobalInit))
|
||||
return 1; // Len = 0 offset by 1.
|
||||
|
||||
// Must be a Constant Array
|
||||
ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit);
|
||||
if (!Array || !Array->getType()->getElementType()->isIntegerTy(8))
|
||||
return false;
|
||||
|
||||
// Get the number of elements in the array
|
||||
uint64_t NumElts = Array->getType()->getNumElements();
|
||||
|
||||
// Traverse the constant array from StartIdx (derived above) which is
|
||||
// the place the GEP refers to in the array.
|
||||
for (unsigned i = StartIdx; i != NumElts; ++i) {
|
||||
Constant *Elt = Array->getOperand(i);
|
||||
ConstantInt *CI = dyn_cast<ConstantInt>(Elt);
|
||||
if (!CI) // This array isn't suitable, non-int initializer.
|
||||
return 0;
|
||||
if (CI->isZero())
|
||||
return i-StartIdx+1; // We found end of string, success!
|
||||
}
|
||||
|
||||
return 0; // The array isn't null terminated, conservatively return 'unknown'.
|
||||
return StrData.size()+1;
|
||||
}
|
||||
|
||||
/// GetStringLength - If we can compute the length of the string pointed to by
|
||||
|
@ -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,103 @@ 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.
|
||||
///
|
||||
// FIXME: Remove this method.
|
||||
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);
|
||||
return ConstantDataArray::getString(Context, Str, AddNull);
|
||||
}
|
||||
|
||||
/// getTypeForElements - Return an anonymous struct type to use for a constant
|
||||
@ -839,8 +895,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.
|
||||
|
Loading…
Reference in New Issue
Block a user