diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp index 0f05cab66d7e..93d157140919 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp @@ -14,6 +14,7 @@ #include "CodeGenFunction.h" #include "CGObjCRuntime.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" @@ -85,7 +86,7 @@ class AggExprEmitter : public StmtVisitor { void EmitMoveFromReturnSlot(const Expr *E, RValue Src); void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, - QualType elementType, InitListExpr *E); + QualType ArrayQTy, InitListExpr *E); AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) { if (CGF.getLangOpts().getGC() && TypeRequiresGCollection(T)) @@ -392,12 +393,15 @@ static bool isTrivialFiller(Expr *E) { /// \brief Emit initialization of an array from an initializer list. void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, - QualType elementType, InitListExpr *E) { + QualType ArrayQTy, InitListExpr *E) { uint64_t NumInitElements = E->getNumInits(); uint64_t NumArrayElements = AType->getNumElements(); assert(NumInitElements <= NumArrayElements); + QualType elementType = + CGF.getContext().getAsArrayType(ArrayQTy)->getElementType(); + // DestPtr is an array*. Construct an elementType* by drilling // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); @@ -409,6 +413,29 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, CharUnits elementAlign = DestPtr.getAlignment().alignmentOfArrayElement(elementSize); + // Consider initializing the array by copying from a global. For this to be + // more efficient than per-element initialization, the size of the elements + // with explicit initializers should be large enough. + if (NumInitElements * elementSize.getQuantity() > 16 && + elementType.isTriviallyCopyableType(CGF.getContext())) { + CodeGen::CodeGenModule &CGM = CGF.CGM; + ConstantEmitter Emitter(CGM); + LangAS AS = ArrayQTy.getAddressSpace(); + if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) { + auto GV = new llvm::GlobalVariable( + CGM.getModule(), C->getType(), + CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true), + llvm::GlobalValue::PrivateLinkage, C, "constinit", + /* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal, + CGM.getContext().getTargetAddressSpace(AS)); + Emitter.finalize(GV); + CharUnits Align = CGM.getContext().getTypeAlignInChars(ArrayQTy); + GV->setAlignment(Align.getQuantity()); + EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GV, ArrayQTy, Align)); + return; + } + } + // Exception safety requires us to destroy all the // already-constructed members if an initializer throws. // For that, we'll need an EH cleanup. @@ -1156,11 +1183,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // Handle initialization of an array. if (E->getType()->isArrayType()) { - QualType elementType = - CGF.getContext().getAsArrayType(E->getType())->getElementType(); - auto AType = cast(Dest.getAddress().getElementType()); - EmitArrayInit(Dest.getAddress(), AType, elementType, E); + EmitArrayInit(Dest.getAddress(), AType, E->getType(), E); return; }