Revert "Emit lifetime.start / lifetime.end markers for unnamed temporary objects."

This reverts commit dbf785a6432f78a8ec229665876647c4cc610d3d, while I qm
investigating a buildbot failure.

llvm-svn: 213380
This commit is contained in:
Arnaud A. de Grandmaison
2014-07-18 14:23:58 +00:00
parent 1be89f4977
commit 18bc4fff48
4 changed files with 24 additions and 149 deletions

View File

@@ -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());
}

View File

@@ -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<llvm::AllocaInst>(Object);
bool useLifetimeMarkers = Alloca && shouldUseLifetimeMarkers(size);
if (useLifetimeMarkers) {
sizeV = llvm::ConstantInt::get(Int64Ty, size);
EmitLifetimeStart(sizeV, Object);
}
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
// If the temporary is a global and has a constant initializer, we may
// have already initialized it.
@@ -374,10 +363,6 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
} else {
EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
}
if (useLifetimeMarkers)
EHStack.pushCleanup<CallLifetimeEnd>(NormalAndEHCleanup, Object, sizeV);
pushTemporaryCleanup(*this, M, E, Object);
// Perform derived-to-base casts and/or field accesses, to get from the

View File

@@ -990,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();
@@ -1690,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);

View File

@@ -1,98 +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());
}