<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 14 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-GB link=blue vlink=purple><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Hi Nico,<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Thanks for letting me know. I’ll be at EuroLLVM Monday/Tuesday, but I would be very happy to investigate your repro after the event.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Cheers,<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Arnaud<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal style='margin-left:36.0pt'><b><span lang=EN-US style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span lang=EN-US style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> thakis@google.com [mailto:thakis@google.com] <b>On Behalf Of </b>Nico Weber<br><b>Sent:</b> 12 April 2015 01:56<br><b>To:</b> Arnaud De Grandmaison<br><b>Cc:</b> cfe-commits@cs.uiuc.edu<br><b>Subject:</b> Re: r234581 - Remove threshold for inserting lifetime markers for named temporaries<o:p></o:p></span></p><p class=MsoNormal style='margin-left:36.0pt'><o:p> </o:p></p><div><p class=MsoNormal style='margin-left:36.0pt'>Hi Arnaud,<o:p></o:p></p><div><p class=MsoNormal style='margin-left:36.0pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:36.0pt'>a few Chromium tests started failing after this commit (<a href="http://crbug.com/476316">http://crbug.com/476316</a>). I speculatively reverted this in r234700 – if it helps with our test failures, I'll get you a repro on Monday, else I'll reland your change.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-left:36.0pt'><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-left:36.0pt'>Nico<o:p></o:p></p></div></div><div><p class=MsoNormal style='margin-left:36.0pt'><o:p> </o:p></p><div><p class=MsoNormal style='margin-left:36.0pt'>On Fri, Apr 10, 2015 at 3:13 AM, Arnaud A. de Grandmaison <<a href="mailto:arnaud.degrandmaison@arm.com" target="_blank">arnaud.degrandmaison@arm.com</a>> wrote:<o:p></o:p></p><p class=MsoNormal style='margin-left:36.0pt'>Author: aadg<br>Date: Fri Apr 10 05:13:52 2015<br>New Revision: 234581<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=234581&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=234581&view=rev</a><br>Log:<br>Remove threshold for inserting lifetime markers for named temporaries<br><br>Now that TailRecursionElimination has been fixed with r222354, the<br>threshold on size for lifetime marker insertion can be removed. This<br>only affects named temporary though, as the patch for unnamed temporaries<br>is still in progress.<br><br>My previous commit (r222993) was not handling debuginfo correctly, but<br>this could only be seen with some asan tests. Basically, lifetime markers<br>are just instrumentation for the compiler's usage and should not affect<br>debug information; however, the cleanup infrastructure was assuming it<br>contained only destructors, i.e. actual code to be executed, and was<br>setting the breakpoint for the end of the function to the closing '}', and<br>not the return statement, in order to show some destructors have been<br>called when leaving the function. This is wrong when the cleanups are only<br>lifetime markers, and this is now fixed.<br><br>Added:<br>    cfe/trunk/test/CodeGen/cleanup-destslot-simple.c<br>    cfe/trunk/test/CodeGen/lifetime-debuginfo-1.c<br>    cfe/trunk/test/CodeGen/lifetime-debuginfo-2.c<br>Modified:<br>    cfe/trunk/lib/CodeGen/CGCall.cpp<br>    cfe/trunk/lib/CodeGen/CGCleanup.cpp<br>    cfe/trunk/lib/CodeGen/CGCleanup.h<br>    cfe/trunk/lib/CodeGen/CGDecl.cpp<br>    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>    cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>    cfe/trunk/lib/CodeGen/EHScopeStack.h<br>    cfe/trunk/test/CodeGenCXX/destructors.cpp<br>    cfe/trunk/test/CodeGenCXX/nrvo.cpp<br>    cfe/trunk/test/CodeGenObjC/arc-blocks.m<br>    cfe/trunk/test/CodeGenObjC/arc-bridged-cast.m<br>    cfe/trunk/test/CodeGenObjC/arc-literals.m<br>    cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m<br>    cfe/trunk/test/CodeGenObjC/arc-ternary-op.m<br>    cfe/trunk/test/CodeGenObjC/arc.m<br>    cfe/trunk/test/CodeGenObjC/exceptions.m<br>    cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-move.mm" target="_blank">arc-move.mm</a><br>    cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-references.mm" target="_blank">arc-references.mm</a><br>    cfe/trunk/test/CodeGenObjCXX/<a href="http://arc.mm" target="_blank">arc.mm</a><br>    cfe/trunk/test/CodeGenObjCXX/<a href="http://literals.mm" target="_blank">literals.mm</a><br><br>Modified: cfe/trunk/lib/CodeGen/CGCall.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGCall.cpp Fri Apr 10 05:13:52 2015<br>@@ -30,6 +30,7 @@<br> #include "llvm/IR/DataLayout.h"<br> #include "llvm/IR/InlineAsm.h"<br> #include "llvm/IR/Intrinsics.h"<br>+#include "llvm/IR/IntrinsicInst.h"<br> #include "llvm/Transforms/Utils/Local.h"<br> #include <sstream><br> using namespace clang;<br>@@ -2216,7 +2217,29 @@ static llvm::StoreInst *findDominatingSt<br>   if (!CGF.ReturnValue->hasOneUse()) {<br>     llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();<br>     if (IP->empty()) return nullptr;<br>-    llvm::StoreInst *store = dyn_cast<llvm::StoreInst>(&IP->back());<br>+    llvm::Instruction *I = &IP->back();<br>+<br>+    // Skip lifetime markers<br>+    for (llvm::BasicBlock::reverse_iterator II = IP->rbegin(),<br>+                                            IE = IP->rend();<br>+         II != IE; ++II) {<br>+      if (llvm::IntrinsicInst *Intrinsic =<br>+              dyn_cast<llvm::IntrinsicInst>(&*II)) {<br>+        if (Intrinsic->getIntrinsicID() == llvm::Intrinsic::lifetime_end) {<br>+          const llvm::Value *CastAddr = Intrinsic->getArgOperand(1);<br>+          ++II;<br>+          if (isa<llvm::BitCastInst>(&*II)) {<br>+            if (CastAddr == &*II) {<br>+              continue;<br>+            }<br>+          }<br>+        }<br>+      }<br>+      I = &*II;<br>+      break;<br>+    }<br>+<br>+    llvm::StoreInst *store = dyn_cast<llvm::StoreInst>(I);<br>     if (!store) return nullptr;<br>     if (store->getPointerOperand() != CGF.ReturnValue) return nullptr;<br>     assert(!store->isAtomic() && !store->isVolatile()); // see below<br>@@ -2314,7 +2337,8 @@ void CodeGenFunction::EmitFunctionEpilog<br><br>       // If there is a dominating store to ReturnValue, we can elide<br>       // the load, zap the store, and usually zap the alloca.<br>-      if (llvm::StoreInst *SI = findDominatingStoreToReturnValue(*this)) {<br>+      if (llvm::StoreInst *SI =<br>+              findDominatingStoreToReturnValue(*this)) {<br>         // Reuse the debug location from the store unless there is<br>         // cleanup code to be emitted between the store and return<br>         // instruction.<br><br>Modified: cfe/trunk/lib/CodeGen/CGCleanup.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.cpp?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.cpp?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGCleanup.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGCleanup.cpp Fri Apr 10 05:13:52 2015<br>@@ -125,6 +125,17 @@ char *EHScopeStack::allocate(size_t Size<br>   return StartOfData;<br> }<br><br>+bool EHScopeStack::containsOnlyLifetimeMarkers(<br>+    EHScopeStack::stable_iterator Old) const {<br>+  for (EHScopeStack::iterator it = begin(); stabilize(it) != Old; it++) {<br>+    EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*it);<br>+    if (!cleanup || !cleanup->isLifetimeMarker())<br>+      return false;<br>+  }<br>+<br>+  return true;<br>+}<br>+<br> EHScopeStack::stable_iterator<br> EHScopeStack::getInnermostActiveNormalCleanup() const {<br>   for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end();<br>@@ -748,7 +759,15 @@ void CodeGenFunction::PopCleanupBlock(bo<br>           Scope.getNumBranchAfters() == 1) {<br>         assert(!BranchThroughDest || !IsActive);<br><br>-        // TODO: clean up the possibly dead stores to the cleanup dest slot.<br>+        // Clean up the possibly dead store to the cleanup dest slot.<br>+        llvm::Instruction *NormalCleanupDestSlot =<br>+            cast<llvm::Instruction>(getNormalCleanupDestSlot());<br>+        if (NormalCleanupDestSlot->hasOneUse()) {<br>+          NormalCleanupDestSlot->user_back()->eraseFromParent();<br>+          NormalCleanupDestSlot->eraseFromParent();<br>+          NormalCleanupDest = nullptr;<br>+        }<br>+<br>         llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);<br>         InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter));<br><br><br>Modified: cfe/trunk/lib/CodeGen/CGCleanup.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.h?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.h?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGCleanup.h (original)<br>+++ cfe/trunk/lib/CodeGen/CGCleanup.h Fri Apr 10 05:13:52 2015<br>@@ -62,6 +62,9 @@ protected:<br>     /// Whether this cleanup is currently active.<br>     unsigned IsActive : 1;<br><br>+    /// Whether this cleanup is a lifetime marker<br>+    unsigned IsLifetimeMarker : 1;<br>+<br>     /// Whether the normal cleanup should test the activation flag.<br>     unsigned TestFlagInNormalCleanup : 1;<br><br>@@ -75,7 +78,7 @@ protected:<br>     /// The number of fixups required by enclosing scopes (not including<br>     /// this one).  If this is the top cleanup scope, all the fixups<br>     /// from this index onwards belong to this scope.<br>-    unsigned FixupDepth : 32 - 17 - NumCommonBits; // currently 13<br>+    unsigned FixupDepth : 32 - 18 - NumCommonBits; // currently 13<br>   };<br><br>   class FilterBitFields {<br>@@ -272,6 +275,7 @@ public:<br>     CleanupBits.IsNormalCleanup = isNormal;<br>     CleanupBits.IsEHCleanup = isEH;<br>     CleanupBits.IsActive = isActive;<br>+    CleanupBits.IsLifetimeMarker = false;<br>     CleanupBits.TestFlagInNormalCleanup = false;<br>     CleanupBits.TestFlagInEHCleanup = false;<br>     CleanupBits.CleanupSize = cleanupSize;<br>@@ -295,6 +299,9 @@ public:<br>   bool isActive() const { return CleanupBits.IsActive; }<br>   void setActive(bool A) { CleanupBits.IsActive = A; }<br><br>+  bool isLifetimeMarker() const { return CleanupBits.IsLifetimeMarker; }<br>+  void setLifetimeMarker() { CleanupBits.IsLifetimeMarker = true; }<br>+<br>   llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }<br>   void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }<br><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=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Apr 10 05:13:52 2015<br>@@ -12,6 +12,7 @@<br> //===----------------------------------------------------------------------===//<br><br> #include "CodeGenFunction.h"<br>+#include "CGCleanup.h"<br> #include "CGDebugInfo.h"<br> #include "CGOpenCLRuntime.h"<br> #include "CodeGenModule.h"<br>@@ -516,10 +517,7 @@ namespace {<br>       : Addr(addr), Size(size) {}<br><br>     void Emit(CodeGenFunction &CGF, Flags flags) override {<br>-      llvm::Value *castAddr = CGF.Builder.CreateBitCast(Addr, CGF.Int8PtrTy);<br>-      CGF.Builder.CreateCall2(CGF.CGM.getLLVMLifetimeEndFn(),<br>-                              Size, castAddr)<br>-        ->setDoesNotThrow();<br>+      CGF.EmitLifetimeEnd(Size, Addr);<br>     }<br>   };<br> }<br>@@ -840,21 +838,6 @@ 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> /// These turn into simple stack objects, or GlobalValues depending on target.<br>@@ -864,6 +847,33 @@ void CodeGenFunction::EmitAutoVarDecl(co<br>   EmitAutoVarCleanups(emission);<br> }<br><br>+/// Emit a lifetime.begin marker if some criteria are satisfied.<br>+/// \return a pointer to the temporary size Value if a marker was emitted, null<br>+/// otherwise<br>+llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,<br>+                                                llvm::Value *Addr) {<br>+  // For now, only in optimized builds.<br>+  if (CGM.getCodeGenOpts().OptimizationLevel == 0)<br>+    return nullptr;<br>+<br>+  llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);<br>+  llvm::Value *Args[] = {<br>+      SizeV,<br>+      new llvm::BitCastInst(Addr, Int8PtrTy, "", Builder.GetInsertBlock())};<br>+  llvm::CallInst *C = llvm::CallInst::Create(CGM.getLLVMLifetimeStartFn(), Args,<br>+                                             "", Builder.GetInsertBlock());<br>+  C->setDoesNotThrow();<br>+  return SizeV;<br>+}<br>+<br>+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {<br>+  llvm::Value *Args[] = {Size, new llvm::BitCastInst(Addr, Int8PtrTy, "",<br>+                                                     Builder.GetInsertBlock())};<br>+  llvm::CallInst *C = llvm::CallInst::Create(CGM.getLLVMLifetimeEndFn(), Args,<br>+                                             "", Builder.GetInsertBlock());<br>+  C->setDoesNotThrow();<br>+}<br>+<br> /// EmitAutoVarAlloca - Emit the alloca and debug information for a<br> /// local variable.  Does not emit initialization or destruction.<br> CodeGenFunction::AutoVarEmission<br>@@ -959,13 +969,8 @@ CodeGenFunction::EmitAutoVarAlloca(const<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>+      if (HaveInsertPoint()) {<br>+        emission.SizeForLifetimeMarkers = EmitLifetimeStart(size, Alloc);<br>       } else {<br>         assert(!emission.useLifetimeMarkers());<br>       }<br>@@ -1311,6 +1316,8 @@ void CodeGenFunction::EmitAutoVarCleanup<br>     EHStack.pushCleanup<CallLifetimeEnd>(NormalCleanup,<br>                                          emission.getAllocatedAddress(),<br>                                          emission.getSizeForLifetimeMarkers());<br>+    EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());<br>+    cleanup.setLifetimeMarker();<br>   }<br><br>   // Check the type for a cleanup.<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=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri Apr 10 05:13:52 2015<br>@@ -12,6 +12,7 @@<br> //===----------------------------------------------------------------------===//<br><br> #include "CodeGenFunction.h"<br>+#include "CGCleanup.h"<br> #include "CGCUDARuntime.h"<br> #include "CGCXXABI.h"<br> #include "CGDebugInfo.h"<br>@@ -243,12 +244,13 @@ void CodeGenFunction::FinishFunction(Sou<br>   // parameters.  Do this in whatever block we're currently in; it's<br>   // important to do this before we enter the return block or return<br>   // edges will be *really* confused.<br>-  bool EmitRetDbgLoc = true;<br>-  if (EHStack.stable_begin() != PrologueCleanupDepth) {<br>+  bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth;<br>+  bool HasOnlyLifetimeMarkers =<br>+      HasCleanups && EHStack.containsOnlyLifetimeMarkers(PrologueCleanupDepth);<br>+  bool EmitRetDbgLoc = !HasCleanups || HasOnlyLifetimeMarkers;<br>+  if (HasCleanups) {<br>     // Make sure the line table doesn't jump back into the body for<br>     // the ret after it's been at EndLoc.<br>-    EmitRetDbgLoc = false;<br>-<br>     if (CGDebugInfo *DI = getDebugInfo())<br>       if (OnlySimpleReturnStmts)<br>         DI->EmitLocation(Builder, EndLoc);<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=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Apr 10 05:13:52 2015<br>@@ -1741,6 +1741,9 @@ public:<br>   void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,<br>                         llvm::Value *Ptr);<br><br>+  llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);<br>+  void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);<br>+<br>   llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);<br>   void EmitCXXDeleteExpr(const CXXDeleteExpr *E);<br><br><br>Modified: cfe/trunk/lib/CodeGen/EHScopeStack.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/EHScopeStack.h?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/EHScopeStack.h?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/EHScopeStack.h (original)<br>+++ cfe/trunk/lib/CodeGen/EHScopeStack.h Fri Apr 10 05:13:52 2015<br>@@ -319,6 +319,10 @@ public:<br>   /// Pops a terminate handler off the stack.<br>   void popTerminate();<br><br>+  // Returns true iff the current scope is either empty or contains only<br>+  // lifetime markers, i.e. no real cleanup code<br>+  bool containsOnlyLifetimeMarkers(stable_iterator Old) const;<br>+<br>   /// Determines whether the exception-scopes stack is empty.<br>   bool empty() const { return StartOfData == EndOfBuffer; }<br><br><br>Added: cfe/trunk/test/CodeGen/cleanup-destslot-simple.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/cleanup-destslot-simple.c?rev=234581&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/cleanup-destslot-simple.c?rev=234581&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGen/cleanup-destslot-simple.c (added)<br>+++ cfe/trunk/test/CodeGen/cleanup-destslot-simple.c Fri Apr 10 05:13:52 2015<br>@@ -0,0 +1,15 @@<br>+// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -gline-tables-only %s -o - | FileCheck %s<br>+<br>+// There is no exception to handle here, lifetime.end is not a destructor,<br>+// so there is no need have cleanup dest slot related code<br>+// CHECK-LABEL: define i32 @test<br>+int test() {<br>+  int x = 3;<br>+  int *volatile p = &x;<br>+  return *p;<br>+// CHECK: [[X:%.*]] = alloca i32<br>+// CHECK: [[P:%.*]] = alloca i32*<br>+// CHECK: call void @llvm.lifetime.start(i64 4, i8* %{{.*}})<br>+// CHECK: call void @llvm.lifetime.start(i64 8, i8* %{{.*}})<br>+// CHECK-NOT: store i32 %{{.*}}, i32* %cleanup.dest.slot<br>+}<br><br>Added: cfe/trunk/test/CodeGen/lifetime-debuginfo-1.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lifetime-debuginfo-1.c?rev=234581&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lifetime-debuginfo-1.c?rev=234581&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGen/lifetime-debuginfo-1.c (added)<br>+++ cfe/trunk/test/CodeGen/lifetime-debuginfo-1.c Fri Apr 10 05:13:52 2015<br>@@ -0,0 +1,13 @@<br>+// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -gline-tables-only %s -o - | FileCheck %s<br>+<br>+// Inserting lifetime markers should not affect debuginfo<br>+<br>+extern int x;<br>+<br>+// CHECK-LABEL: define i32 @f<br>+int f() {<br>+  int *p = &x;<br>+// CHECK: ret i32 %{{.*}}, !dbg [[DI:![0-9]*]]<br>+// CHECK: [[DI]] = !MDLocation(line: [[@LINE+1]]<br>+  return *p;<br>+}<br><br>Added: cfe/trunk/test/CodeGen/lifetime-debuginfo-2.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lifetime-debuginfo-2.c?rev=234581&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lifetime-debuginfo-2.c?rev=234581&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGen/lifetime-debuginfo-2.c (added)<br>+++ cfe/trunk/test/CodeGen/lifetime-debuginfo-2.c Fri Apr 10 05:13:52 2015<br>@@ -0,0 +1,29 @@<br>+// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -gline-tables-only %s -o - | FileCheck %s<br>+<br>+// Inserting lifetime markers should not affect debuginfo: lifetime.end is not<br>+// a destructor, but instrumentation for the compiler. Ensure the debug info for<br>+// the return statement (in the IR) does not point to the function closing '}'<br>+// which is used to show some destructors have been called before leaving the<br>+// function.<br>+<br>+extern int f(int);<br>+extern int g(int);<br>+<br>+// CHECK-LABEL: define i32 @test<br>+int test(int a, int b) {<br>+  int res;<br>+<br>+  if (a==2) {<br>+    int r = f(b);<br>+    res = r + b;<br>+    a += 2;<br>+  } else {<br>+    int r = f(a);<br>+    res = r + a;<br>+    b += 1;<br>+  }<br>+<br>+  return res;<br>+// CHECK: ret i32 %{{.*}}, !dbg [[DI:![0-9]+]]<br>+// CHECK: [[DI]] = !MDLocation(line: [[@LINE-2]]<br>+}<br><br>Modified: cfe/trunk/test/CodeGenCXX/destructors.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenCXX/destructors.cpp (original)<br>+++ cfe/trunk/test/CodeGenCXX/destructors.cpp Fri Apr 10 05:13:52 2015<br>@@ -279,6 +279,8 @@ namespace test5 {<br>   // CHECK5:      [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align<br>   // CHECK5-NEXT: [[EXN:%.*]] = alloca i8*<br>   // CHECK5-NEXT: [[SEL:%.*]] = alloca i32<br>+  // CHECK5-NEXT: [[PELEMS:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to i8*<br>+  // CHECK5-NEXT: call void @llvm.lifetime.start(i64 5, i8* [[PELEMS]])<br>   // CHECK5-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]], [5 x [[A]]]* [[ELEMS]], i32 0, i32 0<br>   // CHECK5-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 5<br>   // CHECK5-NEXT: br label<br>@@ -287,7 +289,8 @@ namespace test5 {<br>   // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]])<br>   // CHECK5:      [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]]<br>   // CHECK5-NEXT: br i1 [[T0]],<br>-  // CHECK5:      ret void<br>+  // CHECK5:      call void @llvm.lifetime.end<br>+  // CHECK5-NEXT: ret void<br>   // lpad<br>   // CHECK5:      [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]]<br>   // CHECK5-NEXT: br i1 [[EMPTY]]<br><br>Modified: cfe/trunk/test/CodeGenCXX/nrvo.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/nrvo.cpp?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/nrvo.cpp?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenCXX/nrvo.cpp (original)<br>+++ cfe/trunk/test/CodeGenCXX/nrvo.cpp Fri Apr 10 05:13:52 2015<br>@@ -54,16 +54,22 @@ X test2(bool B) {<br>   return x;<br><br>   // CHECK: call {{.*}} @_ZN1XC1Ev<br>+  // CHECK-NEXT: {{.*}} getelementptr inbounds %class.X, %class.X* %y, i32 0, i32 0<br>+  // CHECK-NEXT: call void @llvm.lifetime.start<br>   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev<br>   // CHECK: call {{.*}} @_ZN1XC1ERKS_<br>   // CHECK: call {{.*}} @_ZN1XC1ERKS_<br>   // CHECK: call {{.*}} @_ZN1XD1Ev<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK: call {{.*}} @_ZN1XD1Ev<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK: ret void<br><br>   // The block ordering in the -fexceptions IR is unfortunate.<br><br>-  // CHECK-EH:      call {{.*}} @_ZN1XC1Ev<br>+  // CHECK-EH:      call void @llvm.lifetime.start<br>+  // CHECK-EH-NEXT: call {{.*}} @_ZN1XC1Ev<br>+  // CHECK-EH:      call void @llvm.lifetime.start<br>   // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev<br>   // -> %invoke.cont, %lpad<br><br>@@ -96,7 +102,9 @@ X test2(bool B) {<br>   // -> %invoke.cont11, %lpad<br><br>   // %invoke.cont11: normal cleanup for 'x'<br>-  // CHECK-EH:      call {{.*}} @_ZN1XD1Ev<br>+  // CHECK-EH:      call void @llvm.lifetime.end<br>+  // CHECK-EH-NEXT: call {{.*}} @_ZN1XD1Ev<br>+  // CHECK-EH-NEXT: call void @llvm.lifetime.end<br>   // CHECK-EH-NEXT: ret void<br><br>   // %eh.cleanup:  EH cleanup for 'x'<br>@@ -168,9 +176,12 @@ X test6() {<br>   X a __attribute__((aligned(8)));<br>   return a;<br>   // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8<br>+  // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[PTR]])<br>   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])<br>   // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* dereferenceable({{[0-9]+}}) [[A]])<br>   // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[PTR]])<br>   // CHECK-NEXT: ret void<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=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/arc-blocks.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/arc-blocks.m Fri Apr 10 05:13:52 2015<br>@@ -74,6 +74,8 @@ void test3(void (^sink)(id*)) {<br>   // CHECK-NEXT: call i8* @objc_retain(<br>   // CHECK-NEXT: bitcast i8*<br>   // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]<br>+  // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[STRONG]]<br><br>   // CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]<br>@@ -94,6 +96,8 @@ void test3(void (^sink)(id*)) {<br><br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[STRONG]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>+  // CHECK-NEXT: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])<br><br>   // CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]<br>   // CHECK-NEXT: bitcast<br>@@ -167,6 +171,8 @@ void test5(void) {<br>   // CHECK-LABEL:    define void @test5()<br>   // CHECK:      [[VAR:%.*]] = alloca i8*<br>   // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],<br>+  // CHECK-NEXT: [[VARPTR1:%.*]] = bitcast i8** [[VAR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[VARPTR1]])<br>   // CHECK: [[T0:%.*]] = call i8* @test5_source()<br>   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])<br>   // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],<br>@@ -178,6 +184,8 @@ void test5(void) {<br>   // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]<br>   // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to<br>   // CHECK: call void @test5_helper<br>+  // CHECK-NEXT: [[VARPTR2:%.*]] = bitcast i8** [[VAR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[VARPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -190,6 +198,8 @@ void test6(void) {<br>   // CHECK-LABEL:    define void @test6()<br>   // CHECK:      [[VAR:%.*]] = alloca [[BYREF_T:%.*]],<br>   // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],<br>+  // CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 48, i8* [[VARPTR1]])<br>   // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 2<br>   // 0x02000000 - has copy/dispose helpers weak<br>   // CHECK-NEXT: store i32 1107296256, i32* [[T0]]<br>@@ -207,7 +217,9 @@ 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: ret void<br>+  // CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 48, i8* [[VARPTR2]])<br>+  // CHECK-NEXT: ret void<br><br>   // CHECK-LABEL:    define internal void @__Block_byref_object_copy_<br>   // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6<br>@@ -494,6 +506,8 @@ void test13(id x) {<br>   // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})<br>   // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8<br>+  // CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BPTR1]])<br>   // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5<br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8<br>   // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null<br>@@ -519,6 +533,8 @@ void test13(id x) {<br>   // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br>+  // CHECK-NEXT: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[BPTR2]])<br><br>   // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]]<br>   // CHECK-NEXT: br i1 [[T0]]<br>@@ -550,6 +566,8 @@ void test16() {<br>   // CHECK-LABEL: define void @test16(<br>   // CHECK: [[BLKVAR:%.*]]  = alloca void ()*, align 8<br>   // CHECK-NEXT:  [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],<br>+  // CHECK-NEXT:  [[BLKVARPTR1:%.*]] = bitcast void ()** [[BLKVAR]] to i8*<br>+  // CHECK-NEXT:  call void @llvm.lifetime.start(i64 8, i8* [[BLKVARPTR1]])<br>   // CHECK-NEXT:  [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5<br>   // CHECK-NEXT:  store void ()* null, void ()** [[BLKVAR]], align 8<br> }<br><br>Modified: cfe/trunk/test/CodeGenObjC/arc-bridged-cast.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-bridged-cast.m?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-bridged-cast.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/arc-bridged-cast.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/arc-bridged-cast.m Fri Apr 10 05:13:52 2015<br>@@ -31,6 +31,8 @@ void bridge_transfer_from_cf(int *i) {<br>   // CHECK: store i32 17<br>   *i = 17;<br>   // CHECK: call void @objc_release<br>+  // CHECK-NEXT: bitcast<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -50,6 +52,8 @@ void bridge_from_cf(int *i) {<br>   // CHECK: store i32 17<br>   *i = 17;<br>   // CHECK: call void @objc_release<br>+  // CHECK-NEXT: bitcast<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -67,6 +71,8 @@ void bridge_retained_of_cf(int *i) {<br>   // CHECK: store i32 13<br>   // CHECK: store i32 17<br>   *i = 17;<br>+  // CHECK-NEXT: bitcast<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -74,7 +80,8 @@ void bridge_retained_of_cf(int *i) {<br> void bridge_of_cf(int *i) {<br>   // CHECK: store i32 7<br>   *i = 7;<br>-  // CHECK: call i8* @CreateSomething()<br>+  // CHECK: call void @llvm.lifetime.start<br>+  // CHECK-NEXT: call i8* @CreateSomething()<br>   CFTypeRef cf1 = (__bridge CFTypeRef)CreateSomething();<br>   // CHECK-NOT: retain<br>   // CHECK: store i32 11<br>@@ -85,6 +92,8 @@ void bridge_of_cf(int *i) {<br>   // CHECK-NOT: release<br>   // CHECK: store i32 17<br>   *i = 17;<br>+  // CHECK-NEXT: bitcast<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br><br>Modified: cfe/trunk/test/CodeGenObjC/arc-literals.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-literals.m?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-literals.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/arc-literals.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/arc-literals.m Fri Apr 10 05:13:52 2015<br>@@ -27,9 +27,13 @@ void test_numeric() {<br>   // CHECK: call i8* @objc_retainAutoreleasedReturnValue<br>   id charlit = @'a';<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br><br>Modified: cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m Fri Apr 10 05:13:52 2015<br>@@ -7,6 +7,8 @@ void test0() {<br>   PRECISE_LIFETIME id x = test0_helper();<br>   x = 0;<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper()<br>   // CHECK-NEXT: store i8* [[CALL]], i8** [[X]]<br><br>@@ -19,6 +21,8 @@ void test0() {<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]]<br>   // CHECK-NOT:  clang.imprecise_release<br><br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -32,11 +36,17 @@ extern Test1 *test1_helper(void);<br><br> // CHECK-LABEL: define void @test1a()<br> void test1a(void) {<br>+  // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8<br>+  // CHECK:      [[C:%.*]] = alloca i8*, align 8<br>+  // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])<br>   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])<br>   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*<br>   // CHECK-NEXT: store [[TEST1]]* [[T3]]<br>+  // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])<br>@@ -45,9 +55,13 @@ void test1a(void) {<br>   // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*<br>   // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast<br>   // CHECK-NEXT: store i8* [[T6]], i8**<br>+  // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])<br>   // CHECK-NEXT: ret void<br>   Test1 *ptr = test1_helper();<br>   char *c = [(ptr) interior];<br>@@ -55,31 +69,47 @@ void test1a(void) {<br><br> // CHECK-LABEL: define void @test1b()<br> void test1b(void) {<br>+  // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8<br>+  // CHECK:      [[C:%.*]] = alloca i8*, align 8<br>+  // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])<br>   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])<br>   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*<br>   // CHECK-NEXT: store [[TEST1]]* [[T3]]<br>+  // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_<br>   // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast<br>   // CHECK-NEXT: store i8* [[T3]], i8**<br>+  // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]<br>   // CHECK-NOT:  clang.imprecise_release<br>+  // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])<br>   // CHECK-NEXT: ret void<br>   __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();<br>   char *c = [ptr interior];<br> }<br><br> void test1c(void) {<br>+  // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8<br>+  // CHECK:      [[PC:%.*]] = alloca i8*, align 8<br>+  // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])<br>   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])<br>   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*<br>   // CHECK-NEXT: store [[TEST1]]* [[T3]]<br>+  // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])<br>@@ -88,20 +118,30 @@ void test1c(void) {<br>   // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*<br>   // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast<br>   // CHECK-NEXT: store i8* [[T6]], i8**<br>+  // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])<br>   // CHECK-NEXT: ret void<br>   Test1 *ptr = test1_helper();<br>   char *pc = ptr.PropertyReturnsInnerPointer;<br> }<br><br> void test1d(void) {<br>+  // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8<br>+  // CHECK:      [[PC:%.*]] = alloca i8*, align 8<br>+  // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])<br>   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])<br>   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*<br>   // CHECK-NEXT: store [[TEST1]]* [[T3]]<br>+  // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*<br>   // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease<br>@@ -110,9 +150,13 @@ void test1d(void) {<br>   // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8*<br>   // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])<br>   // CHECK-NEXT: store i8* [[CALL1]], i8**<br>+  // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])<br>   // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**<br>   // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[TEN]])<br>+  // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])<br>   // CHECK-NEXT: ret void<br>   __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();<br>   char *pc = ptr.PropertyReturnsInnerPointer;<br><br>Modified: cfe/trunk/test/CodeGenObjC/arc-ternary-op.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-ternary-op.m?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-ternary-op.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/arc-ternary-op.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/arc-ternary-op.m Fri Apr 10 05:13:52 2015<br>@@ -10,6 +10,8 @@ void test0(_Bool cond) {<br>   // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1<br>   // CHECK-NEXT: zext<br>   // CHECK-NEXT: store<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = load i8, i8* [[COND]]<br>   // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1<br>   // CHECK-NEXT: store i1 false, i1* [[RELCOND]]<br>@@ -29,6 +31,8 @@ void test0(_Bool cond) {<br>   // CHECK-NEXT: br label<br>   // CHECK:      [[T0:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br>   id x = (cond ? 0 : test0_helper());<br> }<br>@@ -49,7 +53,11 @@ void test1(int cond) {<br>   // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8*<br>   // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1<br>   // CHECK-NEXT: store i32<br>+  // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[STRONG]]<br>+  // CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKPTR1]])<br>   // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)<br><br>   // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]<br>@@ -93,6 +101,10 @@ void test1(int cond) {<br>   // CHECK-NEXT: br label<br><br>   // CHECK:      call void @objc_destroyWeak(i8** [[WEAK]])<br>+  // CHECK:      [[WEAKPTR2:%.*]] = bitcast i8** [[WEAK]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.end(i64 8, i8* [[WEAKPTR2]])<br>+  // CHECK:      [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])<br>   // CHECK:      ret void<br> }<br><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=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/arc.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/arc.m Fri Apr 10 05:13:52 2015<br>@@ -46,15 +46,17 @@ void test0(id x) {<br> id test1(id x) {<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>   // CHECK-NEXT: [[Y:%.*]] = alloca i8*<br>-  // CHECK-NEXT: alloca i32<br>   // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})<br>   // CHECK-NEXT: store i8* [[PARM]], i8** [[X]]<br>+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[Y]]<br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]<br>   // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T0]])<br>-  // CHECK-NEXT: store i32<br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>+  // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])<br>   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br>   // CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RET]])<br>@@ -99,6 +101,8 @@ void test3_unelided() {<br>   extern void test3_helper(void);<br><br>   // CHECK:      [[X:%.*]] = alloca [[TEST3:%.*]]*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST3]]** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: store [[TEST3]]* null, [[TEST3]]** [[X]], align<br>   Test3 *x;<br><br>@@ -122,12 +126,16 @@ void test3_unelided() {<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]*, [[TEST3]]** [[X]]<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST3]]** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br> // CHECK-LABEL: define void @test3()<br> void test3() {<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br><br>   id x = [[Test3 alloc] initWith: 5];<br><br>@@ -162,7 +170,8 @@ void test3() {<br>   // Cleanup for x.<br>   // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]<br>-<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -244,10 +253,14 @@ id test6_helper(void) __attribute__((ns_<br> // CHECK-LABEL: define void @test6()<br> void test6() {<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[CALL:%.*]] = call i8* @test6_helper()<br>   // CHECK-NEXT: store i8* [[CALL]], i8** [[X]]<br>   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br>   id x = test6_helper();<br> }<br>@@ -256,12 +269,16 @@ void test7_helper(id __attribute__((ns_c<br> // CHECK-LABEL: define void @test7()<br> void test7() {<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[X]]<br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]]<br>   // CHECK-NEXT: call void @test7_helper(i8* [[T1]])<br>   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br>   id x;<br>   test7_helper(x);<br>@@ -271,9 +288,13 @@ id test8_helper(void) __attribute__((ns_<br> void test8() {<br>   __unsafe_unretained id x = test8_helper();<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @test8_helper()<br>   // CHECK-NEXT: store i8* [[T0]], i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -287,7 +308,11 @@ void test10() {<br>   // CHECK-LABEL:      define void @test10()<br>   // CHECK:      [[X:%.*]] = alloca [[TEST10:%.*]]*, align<br>   // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST10]]** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: store [[TEST10]]* null, [[TEST10]]** [[X]]<br>+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])<br>   // CHECK-NEXT: load [[TEST10]]*, [[TEST10]]** [[X]], align<br>   // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}<br>   // CHECK-NEXT: bitcast<br>@@ -307,9 +332,13 @@ void test10() {<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>+  // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST10]]*, [[TEST10]]** [[X]]<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST10]]** [[X]] to i8*<br>+  // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -318,11 +347,15 @@ void test11(id (*f)(void) __attribute__(<br>   // CHECK:      [[F:%.*]] = alloca i8* ()*, align<br>   // CHECK-NEXT: [[X:%.*]] = alloca i8*, align<br>   // CHECK-NEXT: store i8* ()* {{%.*}}, i8* ()** [[F]], align<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = load i8* ()*, i8* ()** [[F]], align<br>   // CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]()<br>   // CHECK-NEXT: store i8* [[T1]], i8** [[X]], align<br>   // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T3]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br>   id x = f();<br> }<br>@@ -335,6 +368,8 @@ void test12(void) {<br>   // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align<br><br>   __weak id x = test12_helper();<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper()<br>   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])<br>   // CHECK-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T1]])<br>@@ -347,12 +382,18 @@ void test12(void) {<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br><br>   id y = x;<br>+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]])<br>   // CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align<br><br>   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[Y]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]], !clang.imprecise_release<br>+  // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])<br>   // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK: ret void<br> }<br><br>@@ -360,6 +401,8 @@ void test12(void) {<br> void test13(void) {<br>   // CHECK-LABEL:      define void @test13()<br>   // CHECK:      [[X:%.*]] = alloca i8*, align<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[X]], align<br>   id x;<br><br>@@ -385,6 +428,8 @@ void test13(void) {<br><br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -617,7 +662,6 @@ void test21(unsigned n) {<br> // CHECK:    define internal i8* @"\01-[Test27 init]"<br> // CHECK:      [[SELF:%.*]] = alloca [[TEST27:%.*]]*,<br> // CHECK-NEXT: [[CMD:%.*]] = alloca i8*,<br>-// CHECK-NEXT: [[DEST:%.*]] = alloca i32<br> // CHECK-NEXT: store [[TEST27]]* {{%.*}}, [[TEST27]]** [[SELF]]<br> // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]<br> // CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]*, [[TEST27]]** [[SELF]]<br>@@ -625,7 +669,6 @@ void test21(unsigned n) {<br> // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])<br> // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST27]]*<br> // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST27]]* [[T3]] to i8*<br>-// CHECK-NEXT: store i32 {{[0-9]+}}, i32* [[DEST]]<br> // CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]*, [[TEST27]]** [[SELF]]<br> // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*<br> // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br>@@ -662,7 +705,6 @@ static id _test29_allocator = 0;<br> // CHECK:    define internal i8* @"\01-[Test29 init]"([[TEST29:%[^*]*]]* {{%.*}},<br> // CHECK:      [[SELF:%.*]] = alloca [[TEST29]]*, align 8<br> // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8<br>-// CHECK-NEXT: [[CLEANUP:%.*]] = alloca i32<br> // CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]]<br> // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]<br><br>@@ -691,7 +733,6 @@ static id _test29_allocator = 0;<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[CALL]]) [[NUW]]<br> // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]*<br> // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8*<br>-// CHECK-NEXT: store i32 1, i32* [[CLEANUP]]<br><br> // Cleanup.<br> // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]]<br>@@ -708,7 +749,6 @@ static id _test29_allocator = 0;<br> // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8<br> // CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca i8*, align 8<br> // CHECK-NEXT: alloca<br>-// CHECK-NEXT: [[CLEANUP:%.*]] = alloca i32<br> // CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]]<br> // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})<br>@@ -747,7 +787,6 @@ static id _test29_allocator = 0;<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]<br> // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]*<br> // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8*<br>-// CHECK-NEXT: store i32 1, i32* [[CLEANUP]]<br><br> // Cleanup.<br> // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[ALLOCATOR]]<br>@@ -776,7 +815,6 @@ char *helper;<br> // CHECK:    define internal i8* @"\01-[Test30 init]"([[TEST30:%[^*]*]]* {{%.*}},<br> // CHECK:      [[RET:%.*]] = alloca [[TEST30]]*<br> // CHECK-NEXT: alloca i8*<br>-// CHECK-NEXT: alloca i32<br> // CHECK-NEXT: store [[TEST30]]* {{%.*}}, [[TEST30]]** [[SELF]]<br> // CHECK-NEXT: store<br><br>@@ -804,7 +842,6 @@ char *helper;<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]])<br> // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST30]]*<br> // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST30]]* [[T1]] to i8*<br>-// CHECK-NEXT: store i32 1<br><br> // Cleanup.<br> // CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]]<br>@@ -863,6 +900,8 @@ void test33(Test33 *ptr) {<br>   // CHECK-NEXT: objc_retain<br>   // CHECK-NEXT: bitcast<br>   // CHECK-NEXT: store<br>+  // CHECK-NEXT: bitcast<br>+  // CHECK-NEXT: call void @llvm.lifetime.start<br>   // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[A]]<br><br>   // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]]<br>@@ -925,6 +964,8 @@ void test33(Test33 *ptr) {<br>   // CHECK-NEXT: load<br>   // CHECK-NEXT: bitcast<br>   // CHECK-NEXT: objc_release<br>+  // CHECK-NEXT: bitcast<br>+  // CHECK-NEXT: call void @llvm.lifetime.end<br>   // CHECK-NEXT: load<br>   // CHECK-NEXT: bitcast<br>   // CHECK-NEXT: objc_release<br>@@ -963,6 +1004,8 @@ void test37(void) {<br>   // CHECK-LABEL:    define void @test37()<br>   // CHECK:      [[VAR:%.*]] = alloca [[TEST37:%.*]]*,<br>   // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[VARPTR1]])<br>   // CHECK-NEXT: store [[TEST37]]* null, [[TEST37]]** [[VAR]]<br><br>   // CHECK-NEXT: [[W0:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]]<br>@@ -983,6 +1026,8 @@ void test37(void) {<br>   // CHECK-NEXT: [[T0:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]]<br>   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8*<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br>+  // CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[VARPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -1039,6 +1084,8 @@ void test47(void) {<br><br>   // CHECK-LABEL:    define void @test47()<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[X]]<br>   // CHECK-NEXT: [[CALL:%.*]] = call i8* @test47_helper()<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])<br>@@ -1051,6 +1098,8 @@ void test47(void) {<br>   // CHECK-NEXT: call void @objc_release(i8* [[T3]])<br>   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T4]])<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -1059,6 +1108,8 @@ void test48(void) {<br>   __weak id x = x = test48_helper();<br>   // CHECK-LABEL:    define void @test48()<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_initWeak(i8** [[X]], i8* null)<br>   // CHECK-NEXT: [[T1:%.*]] = call i8* @test48_helper()<br>   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])<br>@@ -1066,6 +1117,8 @@ void test48(void) {<br>   // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_storeWeak(i8** [[X]], i8* [[T3]])<br>   // CHECK-NEXT: call void @objc_release(i8* [[T2]])<br>   // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -1074,6 +1127,8 @@ void test49(void) {<br>   __autoreleasing id x = x = test49_helper();<br>   // CHECK-LABEL:    define void @test49()<br>   // CHECK:      [[X:%.*]] = alloca i8*<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK-NEXT: store i8* null, i8** [[X]]<br>   // CHECK-NEXT: [[CALL:%.*]] = call i8* @test49_helper()<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])<br>@@ -1081,6 +1136,8 @@ void test49(void) {<br>   // CHECK-NEXT: store i8* [[T2]], i8** [[X]]<br>   // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])<br>   // CHECK-NEXT: store i8* [[T3]], i8** [[X]]<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -1116,10 +1173,14 @@ id test52(void) {<br> // CHECK-LABEL:    define i8* @test52()<br> // CHECK:      [[X:%.*]] = alloca i32<br> // CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*<br>+// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i32* [[X]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[XPTR1]])<br> // CHECK-NEXT: store i32 5, i32* [[X]],<br> // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]],<br> // CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]])<br> // CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]<br>+// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i32* [[X]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[XPTR2]])<br> // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[TMPALLOCA]]<br> // CHECK-NEXT: [[T3:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T2]])<br> // CHECK-NEXT: ret i8* [[T3]]<br>@@ -1134,6 +1195,10 @@ void test53(void) {<br> // CHECK:      [[X:%.*]] = alloca i8*,<br> // CHECK-NEXT: [[Y:%.*]] = alloca i8*,<br> // CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*,<br>+// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>+// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper()<br> // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])<br> // CHECK-NEXT: store i8* [[T1]], i8** [[Y]],<br>@@ -1142,11 +1207,15 @@ void test53(void) {<br> // CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]<br> // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[Y]]<br> // CHECK-NEXT: call void @objc_release(i8* [[T2]])<br>+// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])<br> // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[TMPALLOCA]]<br> // CHECK-NEXT: store i8* [[T3]], i8** [[X]],<br> // CHECK-NEXT: load i8*, i8** [[X]],<br> // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]<br> // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>+// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br> // CHECK-NEXT: ret void<br> }<br><br>@@ -1193,10 +1262,14 @@ void test56_test(void) {<br>   id x = [Test56 make];<br>   // CHECK-LABEL: define void @test56_test()<br>   // CHECK:      [[X:%.*]] = alloca i8*, align 8<br>+  // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK:      [[T0:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(<br>   // CHECK-NEXT: store i8* [[T0]], i8** [[X]]<br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -1276,6 +1349,8 @@ void test61(void) {<br>   // CHECK-NEXT: call void @objc_release(i8* [[T1]])<br>   [test61_make() performSelector: @selector(test61_void)];<br><br>+  // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])<br>   // CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make()<br>   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])<br>   // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_<br>@@ -1288,6 +1363,8 @@ void test61(void) {<br><br>   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[T0]])<br>+  // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -1300,6 +1377,8 @@ void test62(void) {<br>   extern id test62_make(void);<br>   extern void test62_body(void);<br><br>+  // CHECK-NEXT: [[IPTR:%.*]] = bitcast i32* [[I]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR]])<br>   // CHECK-NEXT: store i32 0, i32* [[I]], align 4<br>   // CHECK-NEXT: br label<br><br>@@ -1391,8 +1470,12 @@ void test67(void) {<br> }<br> // CHECK-LABEL:    define void @test67()<br> // CHECK:      [[CL:%.*]] = alloca i8*, align 8<br>+// CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CLPTR1]])<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()<br> // CHECK-NEXT: store i8* [[T0]], i8** [[CL]], align 8<br>+// CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CLPTR2]])<br> // CHECK-NEXT: ret void<br><br> Class test68_helper(void);<br>@@ -1401,11 +1484,15 @@ void test68(void) {<br> }<br> // CHECK-LABEL:    define void @test68()<br> // CHECK:      [[CL:%.*]] = alloca i8*, align 8<br>+// CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CLPTR1]])<br> // CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()<br> // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])<br> // CHECK-NEXT: store i8* [[T1]], i8** [[CL]], align 8<br> // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[CL]]<br> // CHECK-NEXT: call void @objc_release(i8* [[T2]])<br>+// CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CLPTR2]])<br> // CHECK-NEXT: ret void<br><br> // rdar://problem/10564852<br><br>Modified: cfe/trunk/test/CodeGenObjC/exceptions.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/exceptions.m?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/exceptions.m?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjC/exceptions.m (original)<br>+++ cfe/trunk/test/CodeGenObjC/exceptions.m Fri Apr 10 05:13:52 2015<br>@@ -82,6 +82,8 @@ void f3() {<br>   extern void f3_helper(int, int*);<br><br>   // CHECK:      [[X:%.*]] = alloca i32<br>+  // CHECK:      [[XPTR:%.*]] = bitcast i32* [[X]] to i8*<br>+  // CHECK:      call void @llvm.lifetime.start(i64 4, i8* [[XPTR]])<br>   // CHECK:      store i32 0, i32* [[X]]<br>   int x = 0;<br><br>@@ -122,6 +124,7 @@ void f3() {<br>   }<br><br>   // CHECK:      call void @f3_helper(i32 4, i32* [[X]])<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[XPTR]])<br>   // CHECK-NEXT: ret void<br>   f3_helper(4, &x);<br> }<br><br>Modified: cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-move.mm" target="_blank">arc-move.mm</a><br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-move.mm?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-move.mm?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-move.mm" target="_blank">arc-move.mm</a> (original)<br>+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-move.mm" target="_blank">arc-move.mm</a> Fri Apr 10 05:13:52 2015<br>@@ -46,6 +46,10 @@ void library_move(__strong id &x, __stro<br><br> // CHECK-LABEL: define void @_Z12library_moveRU8__strongP11objc_object<br> void library_move(__strong id &y) {<br>+  // CHECK: [[X:%.*]] = alloca i8*, align 8<br>+  // CHECK: [[I:%.*]] = alloca i32, align 4<br>+  // CHECK:      [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])<br>   // CHECK: [[Y:%[a-zA-Z0-9]+]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_<br>   // Load the object<br>   // CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[Y]]<br>@@ -55,10 +59,16 @@ void library_move(__strong id &y) {<br>   // CHECK-NEXT: store i8* [[OBJ]], i8** [[X:%[a-zA-Z0-9]+]]<br>   id x = move(y);<br><br>+  // CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])<br>   // CHECK-NEXT: store i32 17<br>   int i = 17;<br>+  // CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])<br>   // CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[X]]<br>   // CHECK-NEXT: call void @objc_release(i8* [[OBJ]])<br>+  // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br><br>Modified: cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-references.mm" target="_blank">arc-references.mm</a><br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-references.mm?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-references.mm?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-references.mm" target="_blank">arc-references.mm</a> (original)<br>+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-references.mm" target="_blank">arc-references.mm</a> Fri Apr 10 05:13:52 2015<br>@@ -38,11 +38,14 @@ typedef __strong id strong_id;<br><br> //CHECK: define void @_Z5test3v<br> void test3() {<br>+  // CHECK: [[REF:%.*]] = alloca i8**, align 8<br>   // CHECK: call i8* @objc_initWeak<br>   // CHECK-NEXT: store i8**<br>   const __weak id &ref = strong_id();<br>   // CHECK-NEXT: call void @_Z6calleev()<br>   callee();<br>+  // CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR]])<br>   // CHECK-NEXT: call void @objc_destroyWeak<br>   // CHECK-NEXT: ret void<br> }<br>@@ -62,6 +65,7 @@ void sink(__strong A* &&);<br> // CHECK-LABEL: define void @_Z5test5RU8__strongP11objc_object<br> void test5(__strong id &x) {<br>   // CHECK:      [[REFTMP:%.*]] = alloca {{%.*}}*, align 8<br>+  // CHECK:      [[I:%.*]] = alloca i32, align 4<br>   // CHECK:      [[OBJ_ID:%.*]] = call i8* @objc_retain(<br>   // CHECK-NEXT: [[OBJ_A:%.*]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]*<br>   // CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]]<br>@@ -70,8 +74,12 @@ void test5(__strong id &x) {<br>   // CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = load [[A]]*, [[A]]** [[REFTMP]]<br>   // CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8*<br>   // CHECK-NEXT: call void @objc_release<br>+  // CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])<br>   // CHECK-NEXT: store i32 17, i32<br>   int i = 17;<br>+  // CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])<br>   // CHECK-NEXT: ret void<br> }<br><br><br>Modified: cfe/trunk/test/CodeGenObjCXX/<a href="http://arc.mm" target="_blank">arc.mm</a><br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc.mm?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc.mm?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjCXX/<a href="http://arc.mm" target="_blank">arc.mm</a> (original)<br>+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://arc.mm" target="_blank">arc.mm</a> Fri Apr 10 05:13:52 2015<br>@@ -64,7 +64,11 @@ void test34(int cond) {<br>   // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8*<br>   // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1<br>   // CHECK-NEXT: store i32<br>+  // CHECK-NEXT: [[STRONGP:%.*]] = bitcast i8** [[STRONG]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGP]])<br>   // CHECK-NEXT: store i8* null, i8** [[STRONG]]<br>+  // CHECK-NEXT: [[WEAKP:%.*]] = bitcast i8** [[WEAK]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKP]])<br>   // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)<br><br>   // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]<br>@@ -120,56 +124,77 @@ struct Test35_Helper {<br><br> // CHECK-LABEL: define void @_Z6test3513Test35_HelperPS_<br> void test35(Test35_Helper x0, Test35_Helper *x0p) {<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* @_ZN13Test35_Helper11makeObject1Ev<br>   // CHECK-NOT: call i8* @objc_retain<br>   id obj1 = Test35_Helper::makeObject1();<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev<br>   // CHECK-NOT: call i8* @objc_retain<br>   id obj2 = x0.makeObject2();<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev<br>   // CHECK-NOT: call i8* @objc_retain<br>   id obj3 = x0p->makeObject2();<br>   id (Test35_Helper::*pmf)() __attribute__((ns_returns_retained))<br>     = &Test35_Helper::makeObject2;<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* %<br>   // CHECK-NOT: call i8* @objc_retain<br>   id obj4 = (x0.*pmf)();<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* %<br>   // CHECK-NOT: call i8* @objc_retain<br>   id obj5 = (x0p->*pmf)();<br><br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br> // CHECK-LABEL: define void @_Z7test35b13Test35_HelperPS_<br> void test35b(Test35_Helper x0, Test35_Helper *x0p) {<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* @_ZN13Test35_Helper11makeObject3Ev<br>   // CHECK: call i8* @objc_retain<br>   id obj1 = Test35_Helper::makeObject3();<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev<br>   // CHECK: call i8* @objc_retain<br>   id obj2 = x0.makeObject4();<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev<br>   // CHECK: call i8* @objc_retain<br>   id obj3 = x0p->makeObject4();<br>   id (Test35_Helper::*pmf)() = &Test35_Helper::makeObject4;<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* %<br>   // CHECK: call i8* @objc_retain<br>   id obj4 = (x0.*pmf)();<br>+  // CHECK: call void @llvm.lifetime.start<br>   // CHECK: call i8* %<br>   // CHECK: call i8* @objc_retain<br>   id obj5 = (x0p->*pmf)();<br><br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK: call void @objc_release<br>+  // CHECK: call void @llvm.lifetime.end<br>   // CHECK-NEXT: ret void<br> }<br><br>@@ -290,6 +315,8 @@ template void test40_helper<int>();<br> // CHECK-LABEL:    define weak_odr void @_Z13test40_helperIiEvv()<br> // CHECK:      [[X:%.*]] = alloca i8*<br> // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*<br>+// CHECK-NEXT: [[XP:%.*]] = bitcast i8** [[X]] to i8*<br>+// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XP]])<br> // CHECK-NEXT: store i8* null, i8** [[X]]<br> // CHECK:      [[T0:%.*]] = load i8*, i8** [[X]]<br> // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]]<br><br>Modified: cfe/trunk/test/CodeGenObjCXX/<a href="http://literals.mm" target="_blank">literals.mm</a><br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/literals.mm?rev=234581&r1=234580&r2=234581&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/literals.mm?rev=234581&r1=234580&r2=234581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenObjCXX/<a href="http://literals.mm" target="_blank">literals.mm</a> (original)<br>+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://literals.mm" target="_blank">literals.mm</a> Fri Apr 10 05:13:52 2015<br>@@ -16,9 +16,12 @@ struct Y {<br><br> // CHECK-LABEL: define void @_Z10test_arrayv<br> void test_array() {<br>+  // CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8*<br>   // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]<br><br>   // Initializing first element<br>+  // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]])<br>   // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 0<br>   // CHECK-NEXT: call void @_ZN1XC1Ev<br>   // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv<br>@@ -47,6 +50,8 @@ void test_array() {<br>   // CHECK-NEXT: call void @_ZN1XD1Ev<br>   // CHECK-NOT: ret void<br>   // CHECK: call void @objc_release<br>+  // CHECK-NEXT: [[PTR2:%.*]] = bitcast i8** [[ARR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR2]])<br>   // CHECK-NEXT: ret void<br><br>   // Check cleanups<br>@@ -63,9 +68,12 @@ void test_array() {<br> // CHECK-LABEL: define weak_odr void @_Z24test_array_instantiationIiEvv<br> template<typename T><br> void test_array_instantiation() {<br>+  // CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8*<br>   // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]<br><br>   // Initializing first element<br>+  // CHECK:      [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]])<br>   // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 0<br>   // CHECK-NEXT: call void @_ZN1XC1Ev<br>   // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv<br>@@ -94,6 +102,8 @@ void test_array_instantiation() {<br>   // CHECK-NEXT: call void @_ZN1XD1Ev<br>   // CHECK-NOT: ret void<br>   // CHECK: call void @objc_release<br>+  // CHECK-NEXT: [[PTR2]] = bitcast i8** [[ARR]] to i8*<br>+  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR2]])<br>   // CHECK-NEXT: ret void<br><br>   // Check cleanups<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><o:p></o:p></p></div><p class=MsoNormal style='margin-left:36.0pt'><o:p> </o:p></p></div></div></body></html>