Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -1026,7 +1026,11 @@ // regions which need more efforts to handle them correctly. PR28267 // This is rare case, but it's better just omit intrinsics than have // them incorrectly placed. - if (!Bypasses.IsBypassed(&D)) { + // + // Skip emitting lifetime intrinsics when a label was seen in the + // current compound statement and we are compiling for C. + if (!Bypasses.IsBypassed(&D) && + !(!getLangOpts().CPlusPlus && labelSeen())) { uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy); emission.SizeForLifetimeMarkers = EmitLifetimeStart(size, address.getPointer()); Index: lib/CodeGen/CGStmt.cpp =================================================================== --- lib/CodeGen/CGStmt.cpp +++ lib/CodeGen/CGStmt.cpp @@ -375,6 +375,7 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast, AggValueSlot AggSlot) { + LabelSeenRAII LabelSeen(*this); for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end()-GetLast; I != E; ++I) @@ -550,6 +551,7 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { + setLabelSeen(); EmitLabel(S.getDecl()); EmitStmt(S.getSubStmt()); } Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -212,6 +212,33 @@ /// value. This is invalid iff the function has no return value. Address ReturnValue; + /// This is used to keep track of whether a label was seen in compound + /// statements. + llvm::SmallVector LabelSeenStack; + + /// RAII class to push and pop LabelSeenStack. + class LabelSeenRAII { + CodeGenFunction &CGF; + public: + LabelSeenRAII(CodeGenFunction &CGF) : CGF(CGF) { + CGF.LabelSeenStack.push_back(false); + } + + ~LabelSeenRAII() { + bool LabelSeen = CGF.LabelSeenStack.pop_back_val(); + if (!CGF.LabelSeenStack.empty()) + CGF.LabelSeenStack.back() |= LabelSeen; + } + }; + + void setLabelSeen() { + LabelSeenStack.back() = true; + } + + bool labelSeen() const { + return LabelSeenStack.back(); + } + /// AllocaInsertPoint - This is an instruction in the entry block before which /// we prefer to insert allocas. llvm::AssertingVH AllocaInsertPt; Index: test/CodeGen/lifetime2.c =================================================================== --- test/CodeGen/lifetime2.c +++ test/CodeGen/lifetime2.c @@ -1,7 +1,7 @@ -// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefixes=CHECK,O2 -// RUN: %clang -S -emit-llvm -o - -O2 -Xclang -disable-lifetime-markers %s \ +// RUN: %clang_cc1 -S -emit-llvm -o - -O2 -disable-llvm-passes %s | FileCheck %s -check-prefixes=CHECK,O2 +// RUN: %clang_cc1 -S -emit-llvm -o - -O2 -disable-lifetime-markers %s \ // RUN: | FileCheck %s -check-prefixes=CHECK,O0 -// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=CHECK,O0 +// RUN: %clang_cc1 -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=CHECK,O0 extern int bar(char *A, int n); @@ -25,13 +25,11 @@ char x; l1: bar(&x, 1); - // O2: @llvm.lifetime.start(i64 5 - // O2: @llvm.lifetime.end(i64 5 char y[5]; bar(y, 5); goto l1; // Infinite loop - // O2-NOT: @llvm.lifetime.end(i64 1 + // O2-NOT: @llvm.lifetime.end( } // CHECK-LABEL: @goto_bypass @@ -91,3 +89,24 @@ L: bar(&x, 1); } + +// O2-LABEL: define i32 @jump_backward_over_declaration( +// O2-NOT: call void @llvm.lifetime.{{.*}}(i64 4, + +extern void foo2(int p); + +int jump_backward_over_declaration(int a) { + int *p = 0; +label1: + if (p) { + foo2(*p); + return 0; + } + + int i = 999; + if (a != 2) { + p = &i; + goto label1; + } + return -1; +}