summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-05-23 23:41:38 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-05-23 23:41:38 +0000
commit3e268632cf06f34df537d55112de12047c655cc2 (patch)
tree5b5a4870e6e489d98e04af4ed011982b9224b1d8 /clang/lib/CodeGen
parent4672849ead8b34439f90f3a8a26b74b40237bf2e (diff)
downloadbcm5719-llvm-3e268632cf06f34df537d55112de12047c655cc2.tar.gz
bcm5719-llvm-3e268632cf06f34df537d55112de12047c655cc2.zip
Use zeroinitializer for (trailing zero portion of) large array initializers
more reliably. This re-commits r333044 with a fix for PR37560. llvm-svn: 333141
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp170
1 files changed, 91 insertions, 79 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 7b076ea3e65..b26ff3d20e4 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -635,6 +635,60 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM,
return ConstantAddress(GV, Align);
}
+static llvm::Constant *
+EmitArrayConstant(CodeGenModule &CGM, const ConstantArrayType *DestType,
+ llvm::Type *CommonElementType, unsigned ArrayBound,
+ SmallVectorImpl<llvm::Constant *> &Elements,
+ llvm::Constant *Filler) {
+ // Figure out how long the initial prefix of non-zero elements is.
+ unsigned NonzeroLength = ArrayBound;
+ if (Elements.size() < NonzeroLength && Filler->isNullValue())
+ NonzeroLength = Elements.size();
+ if (NonzeroLength == Elements.size()) {
+ while (NonzeroLength > 0 && Elements[NonzeroLength - 1]->isNullValue())
+ --NonzeroLength;
+ }
+
+ if (NonzeroLength == 0) {
+ return llvm::ConstantAggregateZero::get(
+ CGM.getTypes().ConvertType(QualType(DestType, 0)));
+ }
+
+ // Add a zeroinitializer array filler if we have lots of trailing zeroes.
+ unsigned TrailingZeroes = ArrayBound - NonzeroLength;
+ if (TrailingZeroes >= 8) {
+ assert(Elements.size() >= NonzeroLength &&
+ "missing initializer for non-zero element");
+ Elements.resize(NonzeroLength + 1);
+ auto *FillerType =
+ CommonElementType
+ ? CommonElementType
+ : CGM.getTypes().ConvertType(DestType->getElementType());
+ FillerType = llvm::ArrayType::get(FillerType, TrailingZeroes);
+ Elements.back() = llvm::ConstantAggregateZero::get(FillerType);
+ CommonElementType = nullptr;
+ } else if (Elements.size() != ArrayBound) {
+ // Otherwise pad to the right size with the filler if necessary.
+ Elements.resize(ArrayBound, Filler);
+ if (Filler->getType() != CommonElementType)
+ CommonElementType = nullptr;
+ }
+
+ // If all elements have the same type, just emit an array constant.
+ if (CommonElementType)
+ return llvm::ConstantArray::get(
+ llvm::ArrayType::get(CommonElementType, ArrayBound), Elements);
+
+ // We have mixed types. Use a packed struct.
+ llvm::SmallVector<llvm::Type *, 16> Types;
+ Types.reserve(Elements.size());
+ for (llvm::Constant *Elt : Elements)
+ Types.push_back(Elt->getType());
+ llvm::StructType *SType =
+ llvm::StructType::get(CGM.getLLVMContext(), Types, true);
+ return llvm::ConstantStruct::get(SType, Elements);
+}
+
/// This class only needs to handle two cases:
/// 1) Literals (this is used by APValue emission to emit literals).
/// 2) Arrays, structs and unions (outside C++11 mode, we don't currently
@@ -832,68 +886,47 @@ public:
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) {
- llvm::ArrayType *AType =
- cast<llvm::ArrayType>(ConvertType(ILE->getType()));
- llvm::Type *ElemTy = AType->getElementType();
+ auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType());
+ assert(CAT && "can't emit array init for non-constant-bound array");
unsigned NumInitElements = ILE->getNumInits();
- unsigned NumElements = AType->getNumElements();
+ unsigned NumElements = CAT->getSize().getZExtValue();
// Initialising an array requires us to automatically
// initialise any elements that have not been initialised explicitly
unsigned NumInitableElts = std::min(NumInitElements, NumElements);
- QualType EltType = CGM.getContext().getAsArrayType(T)->getElementType();
+ QualType EltType = CAT->getElementType();
// Initialize remaining array elements.
- llvm::Constant *fillC;
- if (Expr *filler = ILE->getArrayFiller())
+ llvm::Constant *fillC = nullptr;
+ if (Expr *filler = ILE->getArrayFiller()) {
fillC = Emitter.tryEmitAbstractForMemory(filler, EltType);
- else
- fillC = Emitter.emitNullForMemory(EltType);
- if (!fillC)
- return nullptr;
-
- // Try to use a ConstantAggregateZero if we can.
- if (fillC->isNullValue() && !NumInitableElts)
- return llvm::ConstantAggregateZero::get(AType);
+ if (!fillC)
+ return nullptr;
+ }
// Copy initializer elements.
SmallVector<llvm::Constant*, 16> Elts;
- Elts.reserve(std::max(NumInitableElts, NumElements));
+ if (fillC && fillC->isNullValue())
+ Elts.reserve(NumInitableElts + 1);
+ else
+ Elts.reserve(NumElements);
- bool RewriteType = false;
- bool AllNullValues = true;
+ llvm::Type *CommonElementType = nullptr;
for (unsigned i = 0; i < NumInitableElts; ++i) {
Expr *Init = ILE->getInit(i);
llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType);
if (!C)
return nullptr;
- RewriteType |= (C->getType() != ElemTy);
+ if (i == 0)
+ CommonElementType = C->getType();
+ else if (C->getType() != CommonElementType)
+ CommonElementType = nullptr;
Elts.push_back(C);
- if (AllNullValues && !C->isNullValue())
- AllNullValues = false;
}
- // If all initializer elements are "zero," then avoid storing NumElements
- // instances of the zero representation.
- if (AllNullValues)
- return llvm::ConstantAggregateZero::get(AType);
-
- RewriteType |= (fillC->getType() != ElemTy);
- Elts.resize(NumElements, fillC);
-
- if (RewriteType) {
- // FIXME: Try to avoid packing the array
- std::vector<llvm::Type*> Types;
- Types.reserve(Elts.size());
- for (unsigned i = 0, e = Elts.size(); i < e; ++i)
- Types.push_back(Elts[i]->getType());
- llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
- Types, true);
- return llvm::ConstantStruct::get(SType, Elts);
- }
-
- return llvm::ConstantArray::get(AType, Elts);
+ return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts,
+ fillC);
}
llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) {
@@ -1889,40 +1922,31 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
case APValue::Union:
return ConstStructBuilder::BuildStruct(*this, Value, DestType);
case APValue::Array: {
- const ArrayType *CAT = CGM.getContext().getAsArrayType(DestType);
+ const ConstantArrayType *CAT =
+ CGM.getContext().getAsConstantArrayType(DestType);
unsigned NumElements = Value.getArraySize();
unsigned NumInitElts = Value.getArrayInitializedElts();
// Emit array filler, if there is one.
llvm::Constant *Filler = nullptr;
- if (Value.hasArrayFiller())
+ if (Value.hasArrayFiller()) {
Filler = tryEmitAbstractForMemory(Value.getArrayFiller(),
CAT->getElementType());
-
- // Emit initializer elements.
- llvm::Type *CommonElementType =
- CGM.getTypes().ConvertType(CAT->getElementType());
-
- // Try to use a ConstantAggregateZero if we can.
- if (Filler && Filler->isNullValue() && !NumInitElts) {
- llvm::ArrayType *AType =
- llvm::ArrayType::get(CommonElementType, NumElements);
- return llvm::ConstantAggregateZero::get(AType);
+ if (!Filler)
+ return nullptr;
}
+ // Emit initializer elements.
SmallVector<llvm::Constant*, 16> Elts;
- Elts.reserve(NumElements);
- for (unsigned I = 0; I < NumElements; ++I) {
- llvm::Constant *C = Filler;
- if (I < NumInitElts) {
- C = tryEmitPrivateForMemory(Value.getArrayInitializedElt(I),
- CAT->getElementType());
- } else if (!Filler) {
- assert(Value.hasArrayFiller() &&
- "Missing filler for implicit elements of initializer");
- C = tryEmitPrivateForMemory(Value.getArrayFiller(),
- CAT->getElementType());
- }
+ if (Filler && Filler->isNullValue())
+ Elts.reserve(NumInitElts + 1);
+ else
+ Elts.reserve(NumElements);
+
+ llvm::Type *CommonElementType = nullptr;
+ for (unsigned I = 0; I < NumInitElts; ++I) {
+ llvm::Constant *C = tryEmitPrivateForMemory(
+ Value.getArrayInitializedElt(I), CAT->getElementType());
if (!C) return nullptr;
if (I == 0)
@@ -1932,20 +1956,8 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
Elts.push_back(C);
}
- if (!CommonElementType) {
- // FIXME: Try to avoid packing the array
- std::vector<llvm::Type*> Types;
- Types.reserve(NumElements);
- for (unsigned i = 0, e = Elts.size(); i < e; ++i)
- Types.push_back(Elts[i]->getType());
- llvm::StructType *SType =
- llvm::StructType::get(CGM.getLLVMContext(), Types, true);
- return llvm::ConstantStruct::get(SType, Elts);
- }
-
- llvm::ArrayType *AType =
- llvm::ArrayType::get(CommonElementType, NumElements);
- return llvm::ConstantArray::get(AType, Elts);
+ return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts,
+ Filler);
}
case APValue::MemberPointer:
return CGM.getCXXABI().EmitMemberPointer(Value, DestType);
OpenPOWER on IntegriCloud