r289623 - When emitting a multidimensional array copy, only emit a single flattened
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 13 17:32:13 PST 2016
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]{};
}
}
More information about the cfe-commits
mailing list