[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.

Michael Gottesman mgottesman at apple.com
Tue Mar 26 07:49:45 PDT 2013


Thanks Bill!

On Mar 25, 2013, at 6:11 PM, Bill Wendling <wendling at apple.com> wrote:

> 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