<div dir="ltr">Hi Nadav!<div><br></div><div style>Cool you guys are working on it! I have a raw local patch that does the same (emits llvm.lifetime start/end intrinsics), and</div><div style>I hope to provide some feedback tomorrow, when I look at this commit in more details. Some of my concerns:</div>
<div style>1) Rafael mentioned a thread where I asked about llvm.lifetime intrinsics semantics and behavior - you may be</div><div style>interested in it. I think we may resurrect it and clarify their semantics.</div><div style>
2) I'm afraid that immediate enabling of stack coloring may break things - I've seen that similar gcc option</div><div style>had to be disabled on some codebases because of the bugs in the code where a local variable was used after</div>
<div style>it went out of scope.</div><div style>3) I actually want to emit lifetime.start/end intrinsics in one of AddressSanitizer modes (to implement -fsanitize=use-after-scope</div><div style>option) to reliably detect bugs in (2).</div>
<div style><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Mar 23, 2013 at 10:43 AM, Nadav Rotem <span dir="ltr"><<a href="mailto:nrotem@apple.com" target="_blank">nrotem@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: nadav<br>
Date: Sat Mar 23 01:43:35 2013<br>
New Revision: 177819<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=177819&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=177819&view=rev</a><br>
Log:<br>
Make clang to mark static stack allocations with lifetime markers to enable a more aggressive stack coloring.<br>
Patch by John McCall with help by Shuxin Yang.<br>
rdar://13115369<br>
<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGen/lifetime2.c<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGDecl.cpp<br>
    cfe/trunk/lib/CodeGen/CGStmt.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
    cfe/trunk/test/CodeGenObjC/arc-blocks.m<br>
    cfe/trunk/test/CodeGenObjC/arc.m<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sat Mar 23 01:43:35 2013<br>
@@ -452,6 +452,22 @@ namespace {<br>
       CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args);<br>
     }<br>
   };<br>
+<br>
+  /// A cleanup to call @llvm.lifetime.end.<br>
+  class CallLifetimeEnd : public EHScopeStack::Cleanup {<br>
+    llvm::Value *Addr;<br>
+    llvm::Value *Size;<br>
+  public:<br>
+    CallLifetimeEnd(llvm::Value *addr, llvm::Value *size)<br>
+      : Addr(addr), Size(size) {}<br>
+<br>
+    void Emit(CodeGenFunction &CGF, Flags flags) {<br>
+      llvm::Value *castAddr = CGF.Builder.CreateBitCast(Addr, CGF.Int8PtrTy);<br>
+      CGF.Builder.CreateCall2(CGF.CGM.getLLVMLifetimeEndFn(),<br>
+                              Size, castAddr)<br>
+        ->setDoesNotThrow();<br>
+    }<br>
+  };<br>
 }<br>
<br>
 /// EmitAutoVarWithLifetime - Does the setup required for an automatic<br>
@@ -756,7 +772,6 @@ static bool shouldUseMemSetPlusStoresToI<br>
   // If a global is all zeros, always use a memset.<br>
   if (isa<llvm::ConstantAggregateZero>(Init)) return true;<br>
<br>
-<br>
   // If a non-zero global is <= 32 bytes, always use a memcpy.  If it is large,<br>
   // do it if it will require 6 or fewer scalar stores.<br>
   // TODO: Should budget depends on the size?  Avoiding a large global warrants<br>
@@ -768,6 +783,20 @@ static bool shouldUseMemSetPlusStoresToI<br>
          canEmitInitWithFewStoresAfterMemset(Init, StoreBudget);<br>
 }<br>
<br>
+/// Should we use the LLVM lifetime intrinsics for the given local variable?<br>
+static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, const VarDecl &D,<br>
+                                     unsigned Size) {<br>
+  // For now, only in optimized builds.<br>
+  if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0)<br>
+    return false;<br>
+<br>
+  // Limit the size of marked objects to 32 bytes. We don't want to increase<br>
+  // compile time by marking tiny objects.<br>
+  unsigned SizeThreshold = 32;<br>
+<br>
+  return Size > SizeThreshold;<br>
+}<br>
+<br>
<br>
 /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a<br>
 /// variable declaration with auto, register, or no storage class specifier.<br>
@@ -870,6 +899,20 @@ CodeGenFunction::EmitAutoVarAlloca(const<br>
               getContext().toCharUnitsFromBits(Target.getPointerAlign(0)));<br>
         Alloc->setAlignment(allocaAlignment.getQuantity());<br>
         DeclPtr = Alloc;<br>
+<br>
+        // Emit a lifetime intrinsic if meaningful.  There's no point<br>
+        // in doing this if we don't have a valid insertion point (?).<br>
+        uint64_t size = CGM.getDataLayout().getTypeAllocSize(LTy);<br>
+        if (HaveInsertPoint() && shouldUseLifetimeMarkers(*this, D, size)) {<br>
+          llvm::Value *sizeV = llvm::ConstantInt::get(Int64Ty, size);<br>
+<br>
+          emission.SizeForLifetimeMarkers = sizeV;<br>
+          llvm::Value *castAddr = Builder.CreateBitCast(Alloc, Int8PtrTy);<br>
+          Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), sizeV, castAddr)<br>
+            ->setDoesNotThrow();<br>
+        } else {<br>
+          assert(!emission.useLifetimeMarkers());<br>
+        }<br>
       }<br>
     } else {<br>
       // Targets that don't support recursion emit locals as globals.<br>
@@ -1215,6 +1258,14 @@ void CodeGenFunction::EmitAutoVarCleanup<br>
<br>
   const VarDecl &D = *emission.Variable;<br>
<br>
+  // Make sure we call @llvm.lifetime.end.  This needs to happen<br>
+  // *last*, so the cleanup needs to be pushed *first*.<br>
+  if (emission.useLifetimeMarkers()) {<br>
+    EHStack.pushCleanup<CallLifetimeEnd>(NormalCleanup,<br>
+                                         emission.getAllocatedAddress(),<br>
+                                         emission.getSizeForLifetimeMarkers());<br>
+  }<br>
+<br>
   // Check the type for a cleanup.<br>
   if (QualType::DestructionKind dtorKind = D.getType().isDestructedType())<br>
     emitAutoVarTypeCleanup(emission, dtorKind);<br>
@@ -1485,6 +1536,22 @@ void CodeGenFunction::pushRegularPartial<br>
                                                   elementType, destroyer);<br>
 }<br>
<br>
+/// Lazily declare the @llvm.lifetime.start intrinsic.<br>
+llvm::Constant *CodeGenModule::getLLVMLifetimeStartFn() {<br>
+  if (LifetimeStartFn) return LifetimeStartFn;<br>
+  LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(),<br>
+                                            llvm::Intrinsic::lifetime_start);<br>
+  return LifetimeStartFn;<br>
+}<br>
+<br>
+/// Lazily declare the @llvm.lifetime.end intrinsic.<br>
+llvm::Constant *CodeGenModule::getLLVMLifetimeEndFn() {<br>
+  if (LifetimeEndFn) return LifetimeEndFn;<br>
+  LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(),<br>
+                                              llvm::Intrinsic::lifetime_end);<br>
+  return LifetimeEndFn;<br>
+}<br>
+<br>
 namespace {<br>
   /// A cleanup to perform a release of an object at the end of a<br>
   /// function.  This is used to balance out the incoming +1 of a<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sat Mar 23 01:43:35 2013<br>
@@ -319,6 +319,12 @@ CodeGenFunction::getJumpDestForLabel(con<br>
 }<br>
<br>
 void CodeGenFunction::EmitLabel(const LabelDecl *D) {<br>
+  // Add this label to the current lexical scope if we're within any<br>
+  // normal cleanups.  Jumps "in" to this label --- when permitted by<br>
+  // the language --- may need to be routed around such cleanups.<br>
+  if (EHStack.hasNormalCleanups() && CurLexicalScope)<br>
+    CurLexicalScope->addLabel(D);<br>
+<br>
   JumpDest &Dest = LabelMap[D];<br>
<br>
   // If we didn't need a forward reference to this label, just go<br>
@@ -330,16 +336,36 @@ void CodeGenFunction::EmitLabel(const La<br>
   // it from the branch-fixups list.<br>
   } else {<br>
     assert(!Dest.getScopeDepth().isValid() && "already emitted label!");<br>
-    Dest = JumpDest(Dest.getBlock(),<br>
-                    EHStack.stable_begin(),<br>
-                    Dest.getDestIndex());<br>
-<br>
+    Dest.setScopeDepth(EHStack.stable_begin());<br>
     ResolveBranchFixups(Dest.getBlock());<br>
   }<br>
<br>
   EmitBlock(Dest.getBlock());<br>
 }<br>
<br>
+/// Change the cleanup scope of the labels in this lexical scope to<br>
+/// match the scope of the enclosing context.<br>
+void CodeGenFunction::LexicalScope::rescopeLabels() {<br>
+  assert(!Labels.empty());<br>
+  EHScopeStack::stable_iterator innermostScope<br>
+    = CGF.EHStack.getInnermostNormalCleanup();<br>
+<br>
+  // Change the scope depth of all the labels.<br>
+  for (SmallVectorImpl<const LabelDecl*>::const_iterator<br>
+         i = Labels.begin(), e = Labels.end(); i != e; ++i) {<br>
+    assert(CGF.LabelMap.count(*i));<br>
+    JumpDest &dest = CGF.LabelMap.find(*i)->second;<br>
+    assert(dest.getScopeDepth().isValid());<br>
+    assert(innermostScope.encloses(dest.getScopeDepth()));<br>
+    dest.setScopeDepth(innermostScope);<br>
+  }<br>
+<br>
+  // Reparent the labels if the new scope also has cleanups.<br>
+  if (innermostScope != EHScopeStack::stable_end() && ParentScope) {<br>
+    ParentScope->Labels.append(Labels.begin(), Labels.end());<br>
+  }<br>
+}<br>
+<br>
<br>
 void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {<br>
   EmitLabel(S.getDecl());<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sat Mar 23 01:43:35 2013<br>
@@ -45,7 +45,7 @@ CodeGenFunction::CodeGenFunction(CodeGen<br>
     IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),<br>
     CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),<br>
     CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),<br>
-    OutermostConditional(0), TerminateLandingPad(0),<br>
+    OutermostConditional(0), CurLexicalScope(0), TerminateLandingPad(0),<br>
     TerminateHandler(0), TrapBB(0) {<br>
   if (!suppressNewContext)<br>
     CGM.getCXXABI().getMangleContext().startNewFunction();<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Mar 23 01:43:35 2013<br>
@@ -562,6 +562,11 @@ public:<br>
     EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }<br>
     unsigned getDestIndex() const { return Index; }<br>
<br>
+    // This should be used cautiously.<br>
+    void setScopeDepth(EHScopeStack::stable_iterator depth) {<br>
+      ScopeDepth = depth;<br>
+    }<br>
+<br>
   private:<br>
     llvm::BasicBlock *Block;<br>
     EHScopeStack::stable_iterator ScopeDepth;<br>
@@ -853,6 +858,8 @@ public:<br>
<br>
   class LexicalScope: protected RunCleanupsScope {<br>
     SourceRange Range;<br>
+    SmallVector<const LabelDecl*, 4> Labels;<br>
+    LexicalScope *ParentScope;<br>
<br>
     LexicalScope(const LexicalScope &) LLVM_DELETED_FUNCTION;<br>
     void operator=(const LexicalScope &) LLVM_DELETED_FUNCTION;<br>
@@ -860,15 +867,23 @@ public:<br>
   public:<br>
     /// \brief Enter a new cleanup scope.<br>
     explicit LexicalScope(CodeGenFunction &CGF, SourceRange Range)<br>
-      : RunCleanupsScope(CGF), Range(Range) {<br>
+      : RunCleanupsScope(CGF), Range(Range), ParentScope(CGF.CurLexicalScope) {<br>
+      CGF.CurLexicalScope = this;<br>
       if (CGDebugInfo *DI = CGF.getDebugInfo())<br>
         DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin());<br>
     }<br>
<br>
+    void addLabel(const LabelDecl *label) {<br>
+      assert(PerformCleanup && "adding label to dead scope?");<br>
+      Labels.push_back(label);<br>
+    }<br>
+<br>
     /// \brief Exit this cleanup scope, emitting any accumulated<br>
     /// cleanups.<br>
     ~LexicalScope() {<br>
-      if (PerformCleanup) endLexicalScope();<br>
+      // If we should perform a cleanup, force them now.  Note that<br>
+      // this ends the cleanup scope before rescoping any labels.<br>
+      if (PerformCleanup) ForceCleanup();<br>
     }<br>
<br>
     /// \brief Force the emission of cleanups now, instead of waiting<br>
@@ -880,9 +895,14 @@ public:<br>
<br>
   private:<br>
     void endLexicalScope() {<br>
+      CGF.CurLexicalScope = ParentScope;<br>
       if (CGDebugInfo *DI = CGF.getDebugInfo())<br>
         DI->EmitLexicalBlockEnd(CGF.Builder, Range.getEnd());<br>
+      if (!Labels.empty())<br>
+        rescopeLabels();<br>
     }<br>
+<br>
+    void rescopeLabels();<br>
   };<br>
<br>
<br>
@@ -1205,6 +1225,8 @@ private:<br>
   /// temporary should be destroyed conditionally.<br>
   ConditionalEvaluation *OutermostConditional;<br>
<br>
+  /// The current lexical scope.<br>
+  LexicalScope *CurLexicalScope;<br>
<br>
   /// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM<br>
   /// type as well as the field number that contains the actual data.<br>
@@ -2001,18 +2023,34 @@ public:<br>
     /// initializer.<br>
     bool IsConstantAggregate;<br>
<br>
+    /// Non-null if we should use lifetime annotations.<br>
+    llvm::Value *SizeForLifetimeMarkers;<br>
+<br>
     struct Invalid {};<br>
     AutoVarEmission(Invalid) : Variable(0) {}<br>
<br>
     AutoVarEmission(const VarDecl &variable)<br>
       : Variable(&variable), Address(0), NRVOFlag(0),<br>
-        IsByRef(false), IsConstantAggregate(false) {}<br>
+        IsByRef(false), IsConstantAggregate(false),<br>
+        SizeForLifetimeMarkers(0) {}<br>
<br>
     bool wasEmittedAsGlobal() const { return Address == 0; }<br>
<br>
   public:<br>
     static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }<br>
<br>
+    bool useLifetimeMarkers() const { return SizeForLifetimeMarkers != 0; }<br>
+    llvm::Value *getSizeForLifetimeMarkers() const {<br>
+      assert(useLifetimeMarkers());<br>
+      return SizeForLifetimeMarkers;<br>
+    }<br>
+<br>
+    /// Returns the raw, allocated address, which is not necessarily<br>
+    /// the address of the object itself.<br>
+    llvm::Value *getAllocatedAddress() const {<br>
+      return Address;<br>
+    }<br>
+<br>
     /// Returns the address of the object within this declaration.<br>
     /// Note that this does not chase the forwarding pointer for<br>
     /// __block decls.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Mar 23 01:43:35 2013<br>
@@ -86,6 +86,7 @@ CodeGenModule::CodeGenModule(ASTContext<br>
     NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),<br>
     BlockObjectAssign(0), BlockObjectDispose(0),<br>
     BlockDescriptorType(0), GenericBlockLiteralType(0),<br>
+    LifetimeStartFn(0), LifetimeEndFn(0),<br>
     SanitizerBlacklist(CGO.SanitizerBlacklistFile),<br>
     SanOpts(SanitizerBlacklist.isIn(M) ?<br>
             SanitizerOptions::Disabled : LangOpts.Sanitize) {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sat Mar 23 01:43:35 2013<br>
@@ -381,6 +381,12 @@ class CodeGenModule : public CodeGenType<br>
     int GlobalUniqueCount;<br>
   } Block;<br>
<br>
+  /// void @llvm.lifetime.start(i64 %size, i8* nocapture <ptr>)<br>
+  llvm::Constant *LifetimeStartFn;<br>
+<br>
+  /// void @llvm.lifetime.end(i64 %size, i8* nocapture <ptr>)<br>
+  llvm::Constant *LifetimeEndFn;<br>
+<br>
   GlobalDecl initializedGlobalDecl;<br>
<br>
   llvm::BlackList SanitizerBlacklist;<br>
@@ -757,6 +763,9 @@ public:<br>
<br>
   ///@}<br>
<br>
+  llvm::Constant *getLLVMLifetimeStartFn();<br>
+  llvm::Constant *getLLVMLifetimeEndFn();<br>
+<br>
   // UpdateCompleteType - Make sure that this type is translated.<br>
   void UpdateCompletedType(const TagDecl *TD);<br>
<br>
<br>
Added: cfe/trunk/test/CodeGen/lifetime2.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lifetime2.c?rev=177819&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lifetime2.c?rev=177819&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGen/lifetime2.c (added)<br>
+++ cfe/trunk/test/CodeGen/lifetime2.c Sat Mar 23 01:43:35 2013<br>
@@ -0,0 +1,17 @@<br>
+// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefix=O2<br>
+// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefix=O0<br>
+<br>
+extern int bar(char *A, int n);<br>
+<br>
+// O0-NOT: @llvm.lifetime.start<br>
+int foo (int n) {<br>
+  if (n) {<br>
+// O2: @llvm.lifetime.start<br>
+    char A[100];<br>
+    return bar(A, 1);<br>
+  } else {<br>
+// O2: @llvm.lifetime.start<br>
+    char A[100];<br>
+    return bar(A, 2);<br>
+  }<br>
+}<br>
<br>
Modified: cfe/trunk/test/CodeGenObjC/arc-blocks.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenObjC/arc-blocks.m (original)<br>
+++ cfe/trunk/test/CodeGenObjC/arc-blocks.m Sat Mar 23 01:43:35 2013<br>
@@ -128,7 +128,7 @@ void test4(void) {<br>
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)<br>
   // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
<br>
   // CHECK:    define internal void @__Block_byref_object_copy_<br>
   // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6<br>
@@ -207,7 +207,7 @@ void test6(void) {<br>
   // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*<br>
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)<br>
   // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
<br>
   // CHECK:    define internal void @__Block_byref_object_copy_<br>
   // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6<br>
@@ -256,14 +256,14 @@ void test7(void) {<br>
   // CHECK:      call void @test7_helper(<br>
   // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})<br>
   // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
<br>
   // CHECK:    define internal void @__test7_block_invoke<br>
   // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5<br>
   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[SLOT]])<br>
   // CHECK-NEXT: call void @test7_consume(i8* [[T0]])<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
<br>
   // CHECK:    define internal void @__copy_helper_block_<br>
   // CHECK:      getelementptr<br>
@@ -296,7 +296,7 @@ void test7(void) {<br>
 // CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]]<br>
 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*<br>
 // CHECK-NEXT: call void @objc_release(i8* [[T2]])<br>
-// CHECK-NEXT: ret void<br>
+// CHECK: ret void<br>
<br>
   extern void test8_helper(void (^)(void));<br>
   test8_helper(^{ (void) self; });<br>
@@ -354,7 +354,7 @@ void test10a(void) {<br>
   // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]<br>
   // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T2]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
 }<br>
<br>
 // <rdar://problem/10402698>: do this copy and dispose with<br>
@@ -374,7 +374,7 @@ void test10a(void) {<br>
 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])<br>
 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*<br>
 // CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8<br>
-// CHECK-NEXT: ret void<br>
+// CHECK: ret void<br>
<br>
 // CHECK: define internal void @__Block_byref_object_dispose<br>
 // CHECK:      [[T0:%.*]] = load i8** {{%.*}}<br>
@@ -418,7 +418,7 @@ void test10b(void) {<br>
   // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]<br>
   // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T2]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
 }<br>
<br>
 // rdar://problem/10088932<br>
@@ -438,7 +438,7 @@ void test11a(void) {<br>
   // CHECK-NEXT: call void @test11_helper(i8* [[T4]])<br>
   // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T5]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
 }<br>
 void test11b(void) {<br>
   int x;<br>
@@ -456,7 +456,7 @@ void test11b(void) {<br>
   // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8<br>
   // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]]<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T5]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
 }<br>
<br>
 // rdar://problem/9979150<br>
<br>
Modified: cfe/trunk/test/CodeGenObjC/arc.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=177819&r1=177818&r2=177819&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=177819&r1=177818&r2=177819&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenObjC/arc.m (original)<br>
+++ cfe/trunk/test/CodeGenObjC/arc.m Sat Mar 23 01:43:35 2013<br>
@@ -353,7 +353,7 @@ void test12(void) {<br>
   // CHECK-NEXT: [[T4:%.*]] = load i8** [[Y]]<br>
   // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]], !clang.imprecise_release<br>
   // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])<br>
-  // CHECK-NEXT: ret void<br>
+  // CHECK: ret void<br>
 }<br>
<br>
 // Indirect consuming calls.<br>
@@ -460,8 +460,9 @@ void test13(void) {<br>
 void test19() {<br>
   // CHECK: define void @test19()<br>
   // CHECK:      [[X:%.*]] = alloca [5 x i8*], align 16<br>
+  // CHECK: call void @llvm.lifetime.start<br>
   // CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8*<br>
-  // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false)<br>
+  // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false)<br>
   id x[5];<br>
<br>
   extern id test19_helper(void);<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div>