Author: rsmith Date: Tue Dec 13 19:32:13 2016 New Revision: 289623 URL: http://llvm.org/viewvc/llvm-project?rev=289623&view=rev Log: When emitting a multidimensional array copy, only emit a single flattened cleanup loop for exception handling.
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=289623&r1=289622&r2=289623&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Tue Dec 13 19:32:13 2016 @@ -164,7 +164,8 @@ public: void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); void VisitChooseExpr(const ChooseExpr *CE); void VisitInitListExpr(InitListExpr *E); - void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, + llvm::Value *outerBegin = nullptr); void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing. void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { @@ -1309,7 +1310,8 @@ void AggExprEmitter::VisitInitListExpr(I cleanupDominator->eraseFromParent(); } -void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { +void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, + llvm::Value *outerBegin) { // Emit the common subexpression. CodeGenFunction::OpaqueValueMapping binding(CGF, E->getCommonExpr()); @@ -1319,15 +1321,18 @@ void AggExprEmitter::VisitArrayInitLoopE if (!numElements) return; - // FIXME: Dig through nested ArrayInitLoopExprs to find the overall array - // size, and only emit a single loop for a multidimensional array. - // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices, "arrayinit.begin"); + // Prepare to special-case multidimensional array initialization: we avoid + // emitting multiple destructor loops in that case. + if (!outerBegin) + outerBegin = begin; + ArrayInitLoopExpr *InnerLoop = dyn_cast<ArrayInitLoopExpr>(E->getSubExpr()); + QualType elementType = CGF.getContext().getAsArrayType(E->getType())->getElementType(); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); @@ -1347,9 +1352,12 @@ void AggExprEmitter::VisitArrayInitLoopE // Prepare for a cleanup. QualType::DestructionKind dtorKind = elementType.isDestructedType(); EHScopeStack::stable_iterator cleanup; - if (CGF.needsEHCleanup(dtorKind)) { - CGF.pushRegularPartialArrayCleanup( - begin, element, elementType, elementAlign, CGF.getDestroyer(dtorKind)); + if (CGF.needsEHCleanup(dtorKind) && !InnerLoop) { + if (outerBegin->getType() != element->getType()) + outerBegin = Builder.CreateBitCast(outerBegin, element->getType()); + CGF.pushRegularPartialArrayCleanup(outerBegin, element, elementType, + elementAlign, + CGF.getDestroyer(dtorKind)); cleanup = CGF.EHStack.stable_begin(); } else { dtorKind = QualType::DK_none; @@ -1363,7 +1371,16 @@ void AggExprEmitter::VisitArrayInitLoopE CodeGenFunction::ArrayInitLoopExprScope Scope(CGF, index); LValue elementLV = CGF.MakeAddrLValue(Address(element, elementAlign), elementType); - EmitInitializationToLValue(E->getSubExpr(), elementLV); + + if (InnerLoop) { + // If the subexpression is an ArrayInitLoopExpr, share its cleanup. + auto elementSlot = AggValueSlot::forLValue( + elementLV, AggValueSlot::IsDestructed, + AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased); + AggExprEmitter(CGF, elementSlot, false) + .VisitArrayInitLoopExpr(InnerLoop, outerBegin); + } else + EmitInitializationToLValue(E->getSubExpr(), elementLV); } // Move on to the next element. Modified: cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp?rev=289623&r1=289622&r2=289623&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Tue Dec 13 19:32:13 2016 @@ -140,7 +140,7 @@ namespace pr28595 { // CHECK: call {{.*}}after_init after_init(); - // CHECK: %[[DST_0:.*]] = getelementptr inbounds [3 x [5 x %[[A]]]], {{.*}}, i64 0, i64 0 + // CHECK: %[[DST_0:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[DST:.*]], i64 0, i64 0 // CHECK: br label // CHECK: %[[I:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[I_NEXT:.*]], {{.*}} ] // CHECK: %[[DST_I:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_0]], i64 %[[I]] @@ -150,6 +150,7 @@ namespace pr28595 { // CHECK: br label // CHECK: %[[J:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[J_NEXT:.*]], {{.*}} ] // CHECK: %[[DST_I_J:.*]] = getelementptr {{.*}} %[[A]]* %[[DST_I_0]], i64 %[[J]] + // CHECK: %[[DST_0_0:.*]] = bitcast [5 x %[[A]]]* %[[DST_0]] to %[[A]]* // CHECK: %[[SRC_I_J:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[SRC_I]], i64 0, i64 %[[J]] // // CHECK: invoke void @_ZN7pr285954TempC1Ev @@ -173,21 +174,12 @@ namespace pr28595 { // CHECK: invoke void @_ZN7pr285954TempD1Ev // CHECK: br label %[[CLEANUP]] // - // FIXME: only emit a single cleanup loop here // CHECK: [[CLEANUP]]: - // CHECK: icmp eq %[[A]]* %[[DST_I_0]], %[[DST_I_J]] + // CHECK: icmp eq %[[A]]* %[[DST_0_0]], %[[DST_I_J]] // CHECK: %[[T0:.*]] = phi %[[A]]* // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) - // CHECK: icmp eq %[[A]]* %[[T1]], %[[DST_I_0]] - // - // CHECK: %[[BEGIN:.*]] = getelementptr {{.*}} %[[DST_0]], i64 0, i64 0 - // CHECK: %[[END:.*]] = getelementptr {{.*}} %[[DST_I]], i64 0, i64 0 - // CHECK: icmp eq %[[A]]* %[[BEGIN]], %[[END]] - // CHECK: %[[T0:.*]] = phi %[[A]]* - // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 - // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) - // CHECK: icmp eq %[[A]]* %[[T1]], %[[BEGIN]] + // CHECK: icmp eq %[[A]]* %[[T1]], %[[DST_0_0]] (void) [array]{}; } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits