From 42d314d1ba7fd02da1784c2a2e26e7a91a6ef1b4 Mon Sep 17 00:00:00 2001 From: "Arnaud A. de Grandmaison" Date: Thu, 2 Oct 2014 12:19:51 +0000 Subject: Emit lifetime.start / lifetime.end markers for unnamed temporary objects. This will give more information to the optimizers so that they can reuse stack slots and reduce stack usage. llvm-svn: 218865 --- clang/lib/CodeGen/CGExpr.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'clang/lib/CodeGen/CGExpr.cpp') diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 4fe37546b60..7b26009a65e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -173,9 +173,10 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E, llvm_unreachable("bad evaluation kind"); } -static void -pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, - const Expr *E, llvm::Value *ReferenceTemporary) { +static void pushTemporaryCleanup(CodeGenFunction &CGF, + const MaterializeTemporaryExpr *M, + const Expr *E, llvm::Value *ReferenceTemporary, + llvm::Value *SizeForLifeTimeMarkers) { // Objective-C++ ARC: // If we are binding a reference to a temporary that has ownership, we // need to perform retain/release operations on the temporary. @@ -242,6 +243,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } } + // Call @llvm.lifetime.end marker for the temporary. + CGF.pushLifetimeEndMarker(M->getStorageDuration(), ReferenceTemporary, + SizeForLifeTimeMarkers); + CXXDestructorDecl *ReferenceTemporaryDtor = nullptr; if (const RecordType *RT = E->getType()->getBaseElementTypeUnsafe()->getAs()) { @@ -296,11 +301,18 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, static llvm::Value * createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, const Expr *Inner) { + const MaterializeTemporaryExpr *M, const Expr *Inner, + llvm::Value *&SizeForLifeTimeMarkers) { + SizeForLifeTimeMarkers = nullptr; switch (M->getStorageDuration()) { case SD_FullExpression: - case SD_Automatic: - return CGF.CreateMemTemp(Inner->getType(), "ref.tmp"); + case SD_Automatic: { + llvm::Value *RefTemp = CGF.CreateMemTemp(Inner->getType(), "ref.tmp"); + uint64_t TempSize = CGF.CGM.getDataLayout().getTypeStoreSize( + CGF.ConvertTypeForMem(Inner->getType())); + SizeForLifeTimeMarkers = CGF.EmitLifetimeStart(TempSize, RefTemp); + return RefTemp; + } case SD_Thread: case SD_Static: @@ -321,7 +333,8 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( M->getType().getObjCLifetime() != Qualifiers::OCL_None && M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { // FIXME: Fold this into the general case below. - llvm::Value *Object = createReferenceTemporary(*this, M, E); + llvm::Value *ObjectSize; + llvm::Value *Object = createReferenceTemporary(*this, M, E, ObjectSize); LValue RefTempDst = MakeAddrLValue(Object, M->getType()); if (auto *Var = dyn_cast(Object)) { @@ -333,7 +346,7 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false); - pushTemporaryCleanup(*this, M, E, Object); + pushTemporaryCleanup(*this, M, E, Object, ObjectSize); return RefTempDst; } @@ -351,8 +364,10 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( } } - // Create and initialize the reference temporary. - llvm::Value *Object = createReferenceTemporary(*this, M, E); + // Create and initialize the reference temporary and get the temporary size + llvm::Value *ObjectSize; + llvm::Value *Object = createReferenceTemporary(*this, M, E, ObjectSize); + if (auto *Var = dyn_cast(Object)) { // If the temporary is a global and has a constant initializer, we may // have already initialized it. @@ -363,7 +378,8 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( } else { EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); } - pushTemporaryCleanup(*this, M, E, Object); + + pushTemporaryCleanup(*this, M, E, Object, ObjectSize); // Perform derived-to-base casts and/or field accesses, to get from the // temporary object we created (and, potentially, for which we extended -- cgit v1.2.3