[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