[llvm] r177952 - [ObjCARC Annotations] Added support for displaying the state of pointers at the bottom/top of BBs of the ARC dataflow analysis for both bottomup and topdown analyses.

Bill Wendling wendling at apple.com
Mon Mar 25 18:11:29 PDT 2013


Michael,

I removed the test case. It's failing on some platforms, but not all of them. Please review.

Thanks!

-bw

On Mar 25, 2013, at 5:42 PM, Michael Gottesman <mgottesman at apple.com> wrote:

> Author: mgottesman
> Date: Mon Mar 25 19:42:09 2013
> New Revision: 177952
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=177952&view=rev
> Log:
> [ObjCARC Annotations] Added support for displaying the state of pointers at the bottom/top of BBs of the ARC dataflow analysis for both bottomup and topdown analyses.
> 
> This will allow for verification and analysis of the merge function of
> the data flow analyses in the ARC optimizer.
> 
> The actual implementation of this feature is by introducing calls to
> the functions llvm.arc.annotation.{bottomup,topdown}.{bbstart,bbend}
> which are only declared. Each such call takes in a pointer to a global
> with the same name as the pointer whose provenance is being tracked and
> a pointer whose name is one of our Sequence states and points to a
> string that contains the same name.
> 
> To ensure that the optimizer does not consider these annotations in any
> way, I made it so that the annotations are considered to be of IC_None
> type.
> 
> A test case is included for this commit and the previous
> ObjCARCAnnotation commit.
> 
> Added:
>    llvm/trunk/test/Transforms/ObjCARC/arc-annotations.ll
> Modified:
>    llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
>    llvm/trunk/lib/Transforms/ObjCARC/ObjCARCUtil.cpp
> 
> Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp?rev=177952&r1=177951&r2=177952&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp (original)
> +++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp Mon Mar 25 19:42:09 2013
> @@ -33,6 +33,7 @@
> #include "llvm/ADT/STLExtras.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> +#include "llvm/IR/IRBuilder.h"
> #include "llvm/IR/LLVMContext.h"
> #include "llvm/Support/CFG.h"
> #include "llvm/Support/Debug.h"
> @@ -763,14 +764,18 @@ static MDString *AppendMDNodeToSourcePtr
>   return Hash;
> }
> 
> +static std::string SequenceToString(Sequence A) {
> +  std::string str;
> +  raw_string_ostream os(str);
> +  os << A;
> +  return os.str();
> +}
> +
> /// Helper function to change a Sequence into a String object using our overload
> /// for raw_ostream so we only have printing code in one location.
> static MDString *SequenceToMDString(LLVMContext &Context,
>                                     Sequence A) {
> -  std::string str;
> -  raw_string_ostream os(str);
> -  os << A;
> -  return MDString::get(Context, os.str());
> +  return MDString::get(Context, SequenceToString(A));
> }
> 
> /// A simple function to generate a MDNode which describes the change in state
> @@ -793,6 +798,79 @@ static void AppendMDNodeToInstForPtr(uns
>   Inst->setMetadata(NodeId, Node);
> }
> 
> +/// Add to the beginning of the basic block llvm.ptr.annotations which show the
> +/// state of a pointer at the entrance to a basic block.
> +static void GenerateARCBBEntranceAnnotation(const char *Name, BasicBlock *BB,
> +                                            Value *Ptr, Sequence Seq) {
> +  Module *M = BB->getParent()->getParent();
> +  LLVMContext &C = M->getContext();
> +  Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
> +  Type *I8XX = PointerType::getUnqual(I8X);
> +  Type *Params[] = {I8XX, I8XX};
> +  FunctionType *FTy = FunctionType::get(Type::getVoidTy(C),
> +                                        ArrayRef<Type*>(Params, 2),
> +                                        /*isVarArg=*/false);
> +  Constant *Callee = M->getOrInsertFunction(Name, FTy);
> +  
> +  IRBuilder<> Builder(BB, BB->getFirstInsertionPt());  
> +  
> +  Value *PtrName;
> +  StringRef Tmp = Ptr->getName();
> +  if (0 == (PtrName = M->getGlobalVariable(Tmp, true))) {
> +    Value *ActualPtrName = Builder.CreateGlobalStringPtr(Tmp,
> +                                                         Tmp + "_STR");
> +    PtrName = new GlobalVariable(*M, I8X, true, GlobalVariable::InternalLinkage,
> +                                 cast<Constant>(ActualPtrName), Tmp); 
> +  }
> +
> +  Value *S;
> +  std::string SeqStr = SequenceToString(Seq);
> +  if (0 == (S = M->getGlobalVariable(SeqStr, true))) {
> +    Value *ActualPtrName = Builder.CreateGlobalStringPtr(SeqStr,
> +                                                         SeqStr + "_STR");
> +    S = new GlobalVariable(*M, I8X, true, GlobalVariable::InternalLinkage,
> +                           cast<Constant>(ActualPtrName), SeqStr);
> +  }
> +
> +  Builder.CreateCall2(Callee, PtrName, S);
> +}
> +
> +/// Add to the end of the basic block llvm.ptr.annotations which show the state
> +/// of the pointer at the bottom of the basic block.
> +static void GenerateARCBBTerminatorAnnotation(const char *Name, BasicBlock *BB,
> +                                              Value *Ptr, Sequence Seq) {
> +  Module *M = BB->getParent()->getParent();
> +  LLVMContext &C = M->getContext();
> +  Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
> +  Type *I8XX = PointerType::getUnqual(I8X);
> +  Type *Params[] = {I8XX, I8XX};
> +  FunctionType *FTy = FunctionType::get(Type::getVoidTy(C),
> +                                        ArrayRef<Type*>(Params, 2),
> +                                        /*isVarArg=*/false);
> +  Constant *Callee = M->getOrInsertFunction(Name, FTy);
> +  
> +  IRBuilder<> Builder(BB, llvm::prior(BB->end()));  
> +  
> +  Value *PtrName;
> +  StringRef Tmp = Ptr->getName();
> +  if (0 == (PtrName = M->getGlobalVariable(Tmp, true))) {
> +    Value *ActualPtrName = Builder.CreateGlobalStringPtr(Tmp,
> +                                                         Tmp + "_STR");
> +    PtrName = new GlobalVariable(*M, I8X, true, GlobalVariable::InternalLinkage,
> +                                 cast<Constant>(ActualPtrName), Tmp); 
> +  }
> +
> +  Value *S;
> +  std::string SeqStr = SequenceToString(Seq);
> +  if (0 == (S = M->getGlobalVariable(SeqStr, true))) {
> +    Value *ActualPtrName = Builder.CreateGlobalStringPtr(SeqStr,
> +                                                         SeqStr + "_STR");
> +    S = new GlobalVariable(*M, I8X, true, GlobalVariable::InternalLinkage,
> +                           cast<Constant>(ActualPtrName), SeqStr);
> +  }
> +  Builder.CreateCall2(Callee, PtrName, S);  
> +}
> +
> /// Adds a source annotation to pointer and a state change annotation to Inst
> /// referencing the source annotation and the old/new state of pointer.
> static void GenerateARCAnnotation(unsigned InstMDId,
> @@ -1816,7 +1894,22 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB
>       assert(I != BBStates.end());
>       MyStates.MergeSucc(I->second);
>     }
> +  }  
> +
> +#ifdef ARC_ANNOTATIONS
> +  if (EnableARCAnnotations) {
> +    // If ARC Annotations are enabled, output the current state of pointers at the
> +    // bottom of the basic block.
> +    for(BBState::ptr_const_iterator I = MyStates.bottom_up_ptr_begin(),
> +          E = MyStates.bottom_up_ptr_end(); I != E; ++I) {
> +      Value *Ptr = const_cast<Value*>(I->first);
> +      Sequence Seq = I->second.GetSeq();
> +      GenerateARCBBTerminatorAnnotation("llvm.arc.annotation.bottomup.bbend",
> +                                        BB, Ptr, Seq);
> +    }
>   }
> +#endif
> +
> 
>   // Visit all the instructions, bottom-up.
>   for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; --I) {
> @@ -1841,6 +1934,20 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB
>       NestingDetected |= VisitInstructionBottomUp(II, BB, Retains, MyStates);
>   }
> 
> +#ifdef ARC_ANNOTATIONS
> +  if (EnableARCAnnotations) {
> +    // If ARC Annotations are enabled, output the current state of pointers at the
> +    // top of the basic block.
> +    for(BBState::ptr_const_iterator I = MyStates.bottom_up_ptr_begin(),
> +          E = MyStates.bottom_up_ptr_end(); I != E; ++I) {
> +      Value *Ptr = const_cast<Value*>(I->first);
> +      Sequence Seq = I->second.GetSeq();
> +      GenerateARCBBEntranceAnnotation("llvm.arc.annotation.bottomup.bbstart",
> +                                      BB, Ptr, Seq);
> +    }
> +  }
> +#endif
> +
>   return NestingDetected;
> }
> 
> @@ -2012,6 +2119,20 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
>     }
>   }
> 
> +#ifdef ARC_ANNOTATIONS
> +  if (EnableARCAnnotations) {
> +    // If ARC Annotations are enabled, output the current state of pointers at the
> +    // top of the basic block.
> +    for(BBState::ptr_const_iterator I = MyStates.top_down_ptr_begin(),
> +          E = MyStates.top_down_ptr_end(); I != E; ++I) {
> +      Value *Ptr = const_cast<Value*>(I->first);
> +      Sequence Seq = I->second.GetSeq();
> +      GenerateARCBBEntranceAnnotation("llvm.arc.annotation.topdown.bbstart",
> +                                      BB, Ptr, Seq);
> +    }
> +  }
> +#endif
> +
>   // Visit all the instructions, top-down.
>   for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
>     Instruction *Inst = I;
> @@ -2021,6 +2142,20 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
>     NestingDetected |= VisitInstructionTopDown(Inst, Releases, MyStates);
>   }
> 
> +#ifdef ARC_ANNOTATIONS
> +  if (EnableARCAnnotations) {
> +    // If ARC Annotations are enabled, output the current state of pointers at the
> +    // bottom of the basic block.
> +    for(BBState::ptr_const_iterator I = MyStates.top_down_ptr_begin(),
> +          E = MyStates.top_down_ptr_end(); I != E; ++I) {
> +      Value *Ptr = const_cast<Value*>(I->first);
> +      Sequence Seq = I->second.GetSeq();
> +      GenerateARCBBTerminatorAnnotation("llvm.arc.annotation.topdown.bbend",
> +                                        BB, Ptr, Seq);
> +    }
> +  }
> +#endif
> +
>   CheckForCFGHazards(BB, BBStates, MyStates);
>   return NestingDetected;
> }
> 
> Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCUtil.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCUtil.cpp?rev=177952&r1=177951&r2=177952&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCUtil.cpp (original)
> +++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCUtil.cpp Mon Mar 25 19:42:09 2013
> @@ -145,6 +145,14 @@ InstructionClass llvm::objcarc::GetFunct
>                 return StringSwitch<InstructionClass>(F->getName())
>                   .Case("objc_moveWeak",              IC_MoveWeak)
>                   .Case("objc_copyWeak",              IC_CopyWeak)
> +                  // Ignore annotation calls. This is important to stop the
> +                  // optimizer from treating annotations as uses which would
> +                  // make the state of the pointers they are attempting to
> +                  // elucidate to be incorrect.
> +                  .Case("llvm.arc.annotation.topdown.bbstart", IC_None)
> +                  .Case("llvm.arc.annotation.topdown.bbend", IC_None)
> +                  .Case("llvm.arc.annotation.bottomup.bbstart", IC_None)
> +                  .Case("llvm.arc.annotation.bottomup.bbend", IC_None)
>                   .Default(IC_CallOrUser);
>           }
> 
> 
> Added: llvm/trunk/test/Transforms/ObjCARC/arc-annotations.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/arc-annotations.ll?rev=177952&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/ObjCARC/arc-annotations.ll (added)
> +++ llvm/trunk/test/Transforms/ObjCARC/arc-annotations.ll Mon Mar 25 19:42:09 2013
> @@ -0,0 +1,306 @@
> +; This file consists of various tests which ensure that the objc-arc-annotations
> +; are working correctly. In the future, I will use this in other lit tests to
> +; check the data flow analysis of ARC.
> +
> +; RUN: opt -S -objc-arc -enable-objc-arc-annotations < %s | FileCheck %s
> +
> +declare i8* @objc_retain(i8*)
> +declare i8* @objc_retainAutoreleasedReturnValue(i8*)
> +declare void @objc_release(i8*)
> +declare i8* @objc_autorelease(i8*)
> +declare i8* @objc_autoreleaseReturnValue(i8*)
> +declare void @objc_autoreleasePoolPop(i8*)
> +declare i8* @objc_autoreleasePoolPush()
> +declare i8* @objc_retainBlock(i8*)
> +
> +declare i8* @objc_retainedObject(i8*)
> +declare i8* @objc_unretainedObject(i8*)
> +declare i8* @objc_unretainedPointer(i8*)
> +
> +declare void @use_pointer(i8*)
> +declare void @callee()
> +declare void @callee_fnptr(void ()*)
> +declare void @invokee()
> +declare i8* @returner()
> +
> +; Simple retain+release pair deletion, with some intervening control
> +; flow and harmless instructions.
> +
> +; CHECK: define void @test0(
> +; CHECK: entry:
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   %0 = tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !0, !llvm.arc.annotation.topdown !1
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Use)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: t:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   store float 2.000000e+00, float* %b, !llvm.arc.annotation.bottomup !2
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: f:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   store i32 7, i32* %x, !llvm.arc.annotation.bottomup !2
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: return:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
> +; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !3, !llvm.arc.annotation.topdown !4
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: }
> +define void @test0(i32* %x, i1 %p) nounwind {
> +entry:
> +  %a = bitcast i32* %x to i8*
> +  %0 = call i8* @objc_retain(i8* %a) nounwind
> +  br i1 %p, label %t, label %f
> +
> +t:
> +  store i8 3, i8* %a
> +  %b = bitcast i32* %x to float*
> +  store float 2.0, float* %b
> +  br label %return
> +
> +f:
> +  store i32 7, i32* %x
> +  br label %return
> +
> +return:
> +  %c = bitcast i32* %x to i8*
> +  call void @objc_release(i8* %c) nounwind
> +  ret void
> +}
> +
> +; Like test0 but the release isn't always executed when the retain is,
> +; so the optimization is not safe.
> +
> +; TODO: Make the objc_release's argument be %0.
> +
> +; CHECK: define void @test1(
> +; CHECK: entry:
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   %0 = tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !5, !llvm.arc.annotation.topdown !6
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: t:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   store float 2.000000e+00, float* %b, !llvm.arc.annotation.bottomup !7
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: f:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   call void @callee(), !llvm.arc.annotation.topdown !8
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_CanRelease)
> +; CHECK: return:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
> +; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !9
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: alt_return:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: }
> +define void @test1(i32* %x, i1 %p, i1 %q) nounwind {
> +entry:
> +  %a = bitcast i32* %x to i8*
> +  %0 = call i8* @objc_retain(i8* %a) nounwind
> +  br i1 %p, label %t, label %f
> +
> +t:
> +  store i8 3, i8* %a
> +  %b = bitcast i32* %x to float*
> +  store float 2.0, float* %b
> +  br label %return
> +
> +f:
> +  store i32 7, i32* %x
> +  call void @callee()
> +  br i1 %q, label %return, label %alt_return
> +
> +return:
> +  %c = bitcast i32* %x to i8*
> +  call void @objc_release(i8* %c) nounwind
> +  ret void
> +
> +alt_return:
> +  ret void
> +}
> +
> +; Don't do partial elimination into two different CFG diamonds.
> +
> +; CHECK: define void @test1b(
> +; CHECK: entry:
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   %0 = tail call i8* @objc_retain(i8* %x) #0, !llvm.arc.annotation.bottomup !10, !llvm.arc.annotation.topdown !11
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: if.then:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_CanRelease)
> +; CHECK:   tail call void @callee(), !llvm.arc.annotation.bottomup !12, !llvm.arc.annotation.topdown !13
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Use)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_CanRelease)
> +; CHECK: if.end:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_CanRelease)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Use)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_CanRelease)
> +; CHECK: if.then3:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_CanRelease)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   tail call void @use_pointer(i8* %x), !llvm.arc.annotation.bottomup !14, !llvm.arc.annotation.topdown !15
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_MovableRelease)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Use)
> +; CHECK: if.end5:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_MovableRelease)
> +; CHECK:   tail call void @objc_release(i8* %x) #0, !clang.imprecise_release !16, !llvm.arc.annotation.bottomup !17
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: }
> +define void @test1b(i8* %x, i1 %p, i1 %q) {
> +entry:
> +  tail call i8* @objc_retain(i8* %x) nounwind
> +  br i1 %p, label %if.then, label %if.end
> +
> +if.then:                                          ; preds = %entry
> +  tail call void @callee()
> +  br label %if.end
> +
> +if.end:                                           ; preds = %if.then, %entry
> +  br i1 %q, label %if.then3, label %if.end5
> +
> +if.then3:                                         ; preds = %if.end
> +  tail call void @use_pointer(i8* %x)
> +  br label %if.end5
> +
> +if.end5:                                          ; preds = %if.then3, %if.end
> +  tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
> +  ret void
> +}
> +
> +; Like test0 but the pointer is passed to an intervening call,
> +; so the optimization is not safe.
> +
> +; CHECK: define void @test2(
> +; CHECK: entry:
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   %e = tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !18, !llvm.arc.annotation.topdown !19
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_CanRelease)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: t:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   store float 2.000000e+00, float* %b, !llvm.arc.annotation.bottomup !20
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: f:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_CanRelease)
> +; CHECK:   call void @use_pointer(i8* %e), !llvm.arc.annotation.bottomup !21, !llvm.arc.annotation.topdown !22
> +; CHECK:   store float 3.000000e+00, float* %d, !llvm.arc.annotation.bottomup !20, !llvm.arc.annotation.topdown !23
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Use)
> +; CHECK: return:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Use)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
> +; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !24, !llvm.arc.annotation.topdown !25
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: }
> +define void @test2(i32* %x, i1 %p) nounwind {
> +entry:
> +  %a = bitcast i32* %x to i8*
> +  %e = call i8* @objc_retain(i8* %a) nounwind
> +  br i1 %p, label %t, label %f
> +
> +t:
> +  store i8 3, i8* %a
> +  %b = bitcast i32* %x to float*
> +  store float 2.0, float* %b
> +  br label %return
> +
> +f:
> +  store i32 7, i32* %x
> +  call void @use_pointer(i8* %e)
> +  %d = bitcast i32* %x to float*
> +  store float 3.0, float* %d
> +  br label %return
> +
> +return:
> +  %c = bitcast i32* %x to i8*
> +  call void @objc_release(i8* %c) nounwind
> +  ret void
> +}
> +
> +; Like test0 but the release is in a loop,
> +; so the optimization is not safe.
> +
> +; TODO: For now, assume this can't happen.
> +
> +; CHECK: define void @test3(
> +; CHECK: entry:
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !26, !llvm.arc.annotation.topdown !27
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
> +; CHECK: loop:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
> +; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
> +; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !28, !llvm.arc.annotation.topdown !29
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: return:
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
> +; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
> +; CHECK: }
> +define void @test3(i32* %x, i1* %q) nounwind {
> +entry:
> +  %a = bitcast i32* %x to i8*
> +  %0 = call i8* @objc_retain(i8* %a) nounwind
> +  br label %loop
> +
> +loop:
> +  %c = bitcast i32* %x to i8*
> +  call void @objc_release(i8* %c) nounwind
> +  %j = load volatile i1* %q
> +  br i1 %j, label %loop, label %return
> +
> +return:
> +  ret void
> +}
> +
> +!0 = metadata !{}
> +
> +; CHECK: !0 = metadata !{metadata !"(test0,%x)", metadata !"S_Use", metadata !"S_None"}
> +; CHECK: !1 = metadata !{metadata !"(test0,%x)", metadata !"S_None", metadata !"S_Retain"}
> +; CHECK: !2 = metadata !{metadata !"(test0,%x)", metadata !"S_Release", metadata !"S_Use"}
> +; CHECK: !3 = metadata !{metadata !"(test0,%x)", metadata !"S_None", metadata !"S_Release"}
> +; CHECK: !4 = metadata !{metadata !"(test0,%x)", metadata !"S_Retain", metadata !"S_None"}
> +; CHECK: !5 = metadata !{metadata !"(test1,%x)", metadata !"S_None", metadata !"S_None"}
> +; CHECK: !6 = metadata !{metadata !"(test1,%x)", metadata !"S_None", metadata !"S_Retain"}
> +; CHECK: !7 = metadata !{metadata !"(test1,%x)", metadata !"S_Release", metadata !"S_Use"}
> +; CHECK: !8 = metadata !{metadata !"(test1,%x)", metadata !"S_Retain", metadata !"S_CanRelease"}
> +; CHECK: !9 = metadata !{metadata !"(test1,%x)", metadata !"S_None", metadata !"S_Release"}
> +; CHECK: !10 = metadata !{metadata !"(test1b,%x)", metadata !"S_None", metadata !"S_None"}
> +; CHECK: !11 = metadata !{metadata !"(test1b,%x)", metadata !"S_None", metadata !"S_Retain"}
> +; CHECK: !12 = metadata !{metadata !"(test1b,%x)", metadata !"S_Use", metadata !"S_CanRelease"}
> +; CHECK: !13 = metadata !{metadata !"(test1b,%x)", metadata !"S_Retain", metadata !"S_CanRelease"}
> +; CHECK: !14 = metadata !{metadata !"(test1b,%x)", metadata !"S_MovableRelease", metadata !"S_Use"}
> +; CHECK: !15 = metadata !{metadata !"(test1b,%x)", metadata !"S_CanRelease", metadata !"S_Use"}
> +; CHECK: !16 = metadata !{}
> +; CHECK: !17 = metadata !{metadata !"(test1b,%x)", metadata !"S_None", metadata !"S_MovableRelease"}
> +; CHECK: !18 = metadata !{metadata !"(test2,%x)", metadata !"S_CanRelease", metadata !"S_None"}
> +; CHECK: !19 = metadata !{metadata !"(test2,%x)", metadata !"S_None", metadata !"S_Retain"}
> +; CHECK: !20 = metadata !{metadata !"(test2,%x)", metadata !"S_Release", metadata !"S_Use"}
> +; CHECK: !21 = metadata !{metadata !"(test2,%x)", metadata !"S_Use", metadata !"S_CanRelease"}
> +; CHECK: !22 = metadata !{metadata !"(test2,%x)", metadata !"S_Retain", metadata !"S_CanRelease"}
> +; CHECK: !23 = metadata !{metadata !"(test2,%x)", metadata !"S_CanRelease", metadata !"S_Use"}
> +; CHECK: !24 = metadata !{metadata !"(test2,%x)", metadata !"S_None", metadata !"S_Release"}
> +; CHECK: !25 = metadata !{metadata !"(test2,%x)", metadata !"S_Use", metadata !"S_None"}
> +; CHECK: !26 = metadata !{metadata !"(test3,%x)", metadata !"S_Release", metadata !"S_None"}
> +; CHECK: !27 = metadata !{metadata !"(test3,%x)", metadata !"S_None", metadata !"S_Retain"}
> +; CHECK: !28 = metadata !{metadata !"(test3,%x)", metadata !"S_None", metadata !"S_Release"}
> +; CHECK: !29 = metadata !{metadata !"(test3,%x)", metadata !"S_Retain", metadata !"S_None"}
> +
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list