From: Arnaud A. de Grandmaison Date: Mon, 21 Jul 2014 19:47:02 +0000 (+0000) Subject: Revert "Emit lifetime.start / lifetime.end markers for unnamed temporary objects." X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6e24a465721c8c919c3f16402e7e756dd2a47a8d;p=platform%2Fupstream%2Fllvm.git Revert "Emit lifetime.start / lifetime.end markers for unnamed temporary objects." This commit did break the sanitizer-x86 bot. Revert it while investigating. llvm-svn: 213579 --- diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 9c8882d..91f8041 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -468,6 +468,22 @@ namespace { CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args); } }; + + /// A cleanup to call @llvm.lifetime.end. + class CallLifetimeEnd : public EHScopeStack::Cleanup { + llvm::Value *Addr; + llvm::Value *Size; + public: + CallLifetimeEnd(llvm::Value *addr, llvm::Value *size) + : Addr(addr), Size(size) {} + + void Emit(CodeGenFunction &CGF, Flags flags) override { + llvm::Value *castAddr = CGF.Builder.CreateBitCast(Addr, CGF.Int8PtrTy); + CGF.Builder.CreateCall2(CGF.CGM.getLLVMLifetimeEndFn(), + Size, castAddr) + ->setDoesNotThrow(); + } + }; } /// EmitAutoVarWithLifetime - Does the setup required for an automatic @@ -786,9 +802,10 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, } /// Should we use the LLVM lifetime intrinsics for the given local variable? -bool CodeGenFunction::shouldUseLifetimeMarkers(unsigned Size) const { +static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, const VarDecl &D, + unsigned Size) { // For now, only in optimized builds. - if (CGM.getCodeGenOpts().OptimizationLevel == 0) + if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) return false; // Limit the size of marked objects to 32 bytes. We don't want to increase @@ -798,6 +815,7 @@ bool CodeGenFunction::shouldUseLifetimeMarkers(unsigned Size) const { return Size > SizeThreshold; } + /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects, or GlobalValues depending on target. @@ -807,18 +825,6 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) { EmitAutoVarCleanups(emission); } -void CodeGenFunction::EmitLifetimeStart(llvm::Value *Size, llvm::Value *Addr) { - llvm::Value *castAddr = Builder.CreateBitCast(Addr, Int8PtrTy); - Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), Size, castAddr) - ->setDoesNotThrow(); -} - -void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) { - llvm::Value *castAddr = Builder.CreateBitCast(Addr, Int8PtrTy); - Builder.CreateCall2(CGM.getLLVMLifetimeEndFn(), Size, castAddr) - ->setDoesNotThrow(); -} - /// EmitAutoVarAlloca - Emit the alloca and debug information for a /// local variable. Does not emit initialization or destruction. CodeGenFunction::AutoVarEmission @@ -914,11 +920,13 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // Emit a lifetime intrinsic if meaningful. There's no point // in doing this if we don't have a valid insertion point (?). uint64_t size = CGM.getDataLayout().getTypeAllocSize(LTy); - if (HaveInsertPoint() && shouldUseLifetimeMarkers(size)) { + if (HaveInsertPoint() && shouldUseLifetimeMarkers(*this, D, size)) { llvm::Value *sizeV = llvm::ConstantInt::get(Int64Ty, size); emission.SizeForLifetimeMarkers = sizeV; - EmitLifetimeStart(sizeV, Alloc); + llvm::Value *castAddr = Builder.CreateBitCast(Alloc, Int8PtrTy); + Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), sizeV, castAddr) + ->setDoesNotThrow(); } else { assert(!emission.useLifetimeMarkers()); } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 2c9c2f1..512b323 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -353,17 +353,6 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( // Create and initialize the reference temporary. llvm::Value *Object = createReferenceTemporary(*this, M, E); - - uint64_t size = - CGM.getDataLayout().getTypeStoreSize(ConvertTypeForMem(E->getType())); - llvm::Value *sizeV = nullptr; - llvm::AllocaInst *Alloca = dyn_cast(Object); - bool useLifetimeMarkers = Alloca && shouldUseLifetimeMarkers(size); - if (useLifetimeMarkers) { - sizeV = llvm::ConstantInt::get(Int64Ty, size); - EmitLifetimeStart(sizeV, Object); - } - if (auto *Var = dyn_cast(Object)) { // If the temporary is a global and has a constant initializer, we may // have already initialized it. @@ -374,20 +363,6 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( } else { EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); } - - if (useLifetimeMarkers) - switch (M->getStorageDuration()) { - case SD_FullExpression: - EHStack.pushCleanup(NormalAndEHCleanup, Object, sizeV); - break; - case SD_Automatic: - pushCleanupAfterFullExpr(NormalAndEHCleanup, Object, - sizeV); - break; - default: - llvm_unreachable("unexpected storage duration for Lifetime markers"); - } - pushTemporaryCleanup(*this, M, E, Object); // Perform derived-to-base casts and/or field accesses, to get from the diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index cd668e0..59cc30d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -436,23 +436,6 @@ public: new (Buffer + sizeof(Header)) T(a0, a1, a2, a3); } - /// \brief Queue a cleanup to be pushed after finishing the current - /// full-expression. - template - void pushCleanupAfterFullExpr(CleanupKind Kind, A0 a0, A1 a1) { - assert(!isInConditionalBranch() && "can't defer conditional cleanup"); - - LifetimeExtendedCleanupHeader Header = { sizeof(T), Kind }; - - size_t OldSize = LifetimeExtendedCleanupStack.size(); - LifetimeExtendedCleanupStack.resize( - LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size); - - char *Buffer = &LifetimeExtendedCleanupStack[OldSize]; - new (Buffer) LifetimeExtendedCleanupHeader(Header); - new (Buffer + sizeof(Header)) T(a0, a1); - } - /// Set up the last cleaup that was pushed as a conditional /// full-expression cleanup. void initFullExprCleanup(); @@ -1007,23 +990,6 @@ private: void EmitOpenCLKernelMetadata(const FunctionDecl *FD, llvm::Function *Fn); - /// Should we use the LLVM lifetime intrinsics for a local variable of the - /// given size in bytes ? - bool shouldUseLifetimeMarkers(unsigned Size) const; - - /// A cleanup to call @llvm.lifetime.end. - class CallLifetimeEnd : public EHScopeStack::Cleanup { - llvm::Value *Addr; - llvm::Value *Size; - public: - CallLifetimeEnd(llvm::Value *addr, llvm::Value *size) - : Addr(addr), Size(size) {} - - void Emit(CodeGenFunction &CGF, Flags flags) override { - CGF.EmitLifetimeEnd(Size, Addr); - } - }; - public: CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext=false); ~CodeGenFunction(); @@ -1707,9 +1673,6 @@ public: void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType, llvm::Value *Ptr); - void EmitLifetimeStart(llvm::Value *Size, llvm::Value *Addr); - void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr); - llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); void EmitCXXDeleteExpr(const CXXDeleteExpr *E); diff --git a/clang/test/CodeGenCXX/unnamed-object-lifetime.cpp b/clang/test/CodeGenCXX/unnamed-object-lifetime.cpp deleted file mode 100644 index c1422bc..0000000 --- a/clang/test/CodeGenCXX/unnamed-object-lifetime.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s - -// Test lifetime marker generation for unnamed temporary objects. - -struct X { - X(); - ~X(); - char t[33]; // make the class big enough so that lifetime markers get inserted -}; - -extern void useX(const X &); - -// CHECK-LABEL: define void @_Z6simplev -// CHECK-EH-LABEL: define void @_Z6simplev -void simple() { - // CHECK: [[ALLOCA:%.*]] = alloca %struct.X - // CHECK: [[PTR:%.*]] = getelementptr inbounds %struct.X* [[ALLOCA]], i32 0, i32 0, i32 0 - // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[PTR]]) - // CHECK-NEXT: call void @_ZN1XC1Ev - // CHECK-NEXT: call void @_Z4useXRK1X - // CHECK-NEXT: call void @_ZN1XD1Ev - // CHECK-NEXT: call void @llvm.lifetime.end(i64 33, i8* [[PTR]]) - // - // CHECK-EH: [[ALLOCA:%.*]] = alloca %struct.X - // CHECK-EH: [[PTR:%.*]] = getelementptr inbounds %struct.X* [[ALLOCA]], i32 0, i32 0, i32 0 - // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[PTR]]) - // CHECK-EH-NEXT: call void @_ZN1XC1Ev - // CHECK-EH: invoke void @_Z4useXRK1X - // CHECK-EH: invoke void @_ZN1XD1Ev - // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[PTR]]) - // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[PTR]]) - useX(X()); -} - -struct Y { - Y(){} - ~Y(){} - char t[34]; // make the class big enough so that lifetime markers get inserted -}; - -extern void useY(const Y &); - -// Check lifetime markers are inserted, despite Y's trivial constructor & destructor -// CHECK-LABEL: define void @_Z7trivialv -// CHECK-EH-LABEL: define void @_Z7trivialv -void trivial() { - // CHECK: [[ALLOCA:%.*]] = alloca %struct.Y - // CHECK: [[PTR:%.*]] = getelementptr inbounds %struct.Y* [[ALLOCA]], i32 0, i32 0, i32 0 - // CHECK: call void @llvm.lifetime.start(i64 34, i8* [[PTR]]) - // CHECK-NEXT: call void @_Z4useYRK1Y - // CHECK-NEXT: call void @llvm.lifetime.end(i64 34, i8* [[PTR]]) - // - // CHECK-EH: [[ALLOCA:%.*]] = alloca %struct.Y - // CHECK-EH: [[PTR:%.*]] = getelementptr inbounds %struct.Y* [[ALLOCA]], i32 0, i32 0, i32 0 - // CHECK-EH: call void @llvm.lifetime.start(i64 34, i8* [[PTR]]) - // CHECK-EH-NEXT: invoke void @_Z4useYRK1Y - // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[PTR]]) - // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[PTR]]) - useY(Y()); -} - -struct Z { - Z(); - ~Z(); - char t; -}; - -extern void useZ(const Z &); - -// Check lifetime markers are not inserted if the unnamed object is too small -// CHECK-LABEL: define void @_Z8tooSmallv -// CHECK-EH-LABEL: define void @_Z8tooSmallv -void tooSmall() { - // CHECK-NOT: call void @llvm.lifetime.start - // CHECK: call void @_Z4useZRK1Z - // CHECK-NOT: call void @llvm.lifetime.end - // CHECK: ret - // - // CHECK-EH-NOT: call void @llvm.lifetime.start - // CHECK-EH: invoke void @_Z4useZRK1Z - // CHECK-EH-NOT: call void @llvm.lifetime.end - // CHECK-EH: ret - useZ(Z()); -} - -// Check the lifetime are inserted at the right place in their respective scope -// CHECK-LABEL: define void @_Z6scopesv -void scopes() { - // CHECK: alloca %struct - // CHECK: alloca %struct - // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[X:%.*]]) - // CHECK: call void @llvm.lifetime.end(i64 33, i8* [[X]]) - // CHECK: call void @llvm.lifetime.start(i64 34, i8* [[Y:%.*]]) - // CHECK: call void @llvm.lifetime.end(i64 34, i8* [[Y]]) - useX(X()); - useY(Y()); -} - -struct L { - L(int); - ~L(); - char t[33]; -}; - -// Check the lifetime-extended case -// CHECK-LABEL: define void @_Z16extendedLifetimev -void extendedLifetime() { - extern void useL(const L&); - - // CHECK: [[A:%.*]] = alloca %struct.L - // CHECK: [[P:%.*]] = getelementptr inbounds %struct.L* [[A]], i32 0, i32 0, i32 0 - // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[P]]) - // CHECK: call void @_ZN1LC1Ei(%struct.L* [[A]], i32 2) - // CHECK-NOT: call void @llvm.lifetime.end(i64 33, i8* [[P]]) - // CHECK: call void @_Z4useLRK1L(%struct.L* dereferenceable(33) [[A]]) - // CHECK: call void @_ZN1LD1Ev(%struct.L* [[A]]) - // CHECK-NEXT: call void @llvm.lifetime.end(i64 33, i8* [[P]]) - // - // CHECK-EH: [[A:%.*]] = alloca %struct.L - // CHECK-EH: [[P:%.*]] = getelementptr inbounds %struct.L* [[A]], i32 0, i32 0, i32 0 - // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[P]]) - // CHECK-EH: call void @_ZN1LC1Ei(%struct.L* [[A]], i32 2) - // CHECK-EH-NOT: call void @llvm.lifetime.end(i64 33, i8* [[P]]) - // CHECK-EH: invoke void @_Z4useLRK1L(%struct.L* dereferenceable(33) [[A]]) - // CHECK-EH: invoke void @_ZN1LD1Ev(%struct.L* [[A]]) - // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]]) - // CHECK-EH: invoke void @_ZN1LD1Ev(%struct.L* [[A]]) - // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]]) - const L &l = 2; - useL(l); -}