[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