[llvm] r189869 - [objc-arc] Turn off the objc_retainBlock -> objc_retain optimization.

Bob Wilson bob.wilson at apple.com
Wed Sep 4 10:31:24 PDT 2013


I already mentioned this to Michael off-line, but for the benefit of others reading the list, this is not the right way to temporarily disable something. It would be much better to make small changes to prevent the code from being run, e.g., "if (0) ….", and then change the RUN lines from the tests to disable them.  Removing all the code like this and then adding it back once you have a fix creates a lot of unnecessary churn in the sources.  That makes it harder to search through the source history, increases the chances of merge conflicts for other branches, and makes it hard to cherry-pick fixes elsewhere.

Since this is already done, there's no point in re-doing it now, though.

On Sep 3, 2013, at 3:40 PM, Michael Gottesman <mgottesman at apple.com> wrote:

> Author: mgottesman
> Date: Tue Sep  3 17:40:54 2013
> New Revision: 189869
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=189869&view=rev
> Log:
> [objc-arc] Turn off the objc_retainBlock -> objc_retain optimization.
> 
> The reason that I am turning off this optimization is that there is an
> additional case where a block can escape that has come up. Specifically, this
> occurs when a block is used in a scope outside of its current scope.
> 
> This can cause a captured retainable object pointer whose life is preserved by
> the objc_retainBlock to be deallocated before the block is invoked.
> 
> An example of the code needed to trigger the bug is:
> 
> ----
> \#import <Foundation/Foundation.h>
> int main(int argc, const char * argv[]) {
>  void (^somethingToDoLater)();
> 
>  {
>    NSObject *obj = [NSObject new];
> 
>    somethingToDoLater = ^{
>      [obj self]; // Crashes here
>    };
>  }
> 
>  NSLog(@"test.");
> 
>  somethingToDoLater();
>  return 0;
> }
> ----
> 
> In the next commit, I remove all the dead code that results from this.
> 
> Once I put in the fixing commit I will bring back the tests that I deleted in
> this commit.
> 
> rdar://14802782.
> rdar://14868830.
> 
> Removed:
>    llvm/trunk/test/Transforms/ObjCARC/no-objc-arc-exceptions.ll
>    llvm/trunk/test/Transforms/ObjCARC/retain-block-alloca.ll
>    llvm/trunk/test/Transforms/ObjCARC/retain-block-escape-analysis.ll
>    llvm/trunk/test/Transforms/ObjCARC/retain-block-load.ll
>    llvm/trunk/test/Transforms/ObjCARC/retain-block.ll
> Modified:
>    llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
> 
> Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp?rev=189869&r1=189868&r2=189869&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp (original)
> +++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp Tue Sep  3 17:40:54 2013
> @@ -1510,11 +1510,6 @@ void ObjCARCOpt::OptimizeIndividualCalls
>       }
>       break;
>     }
> -    case IC_RetainBlock:
> -      // If we strength reduce an objc_retainBlock to an objc_retain, continue
> -      // onto the objc_retain peephole optimizations. Otherwise break.
> -      OptimizeRetainBlockCall(F, Inst, Class);
> -      break;
>     case IC_RetainRV:
>       if (OptimizeRetainRVCall(F, Inst))
>         continue;
> 
> Removed: llvm/trunk/test/Transforms/ObjCARC/no-objc-arc-exceptions.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/no-objc-arc-exceptions.ll?rev=189868&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/ObjCARC/no-objc-arc-exceptions.ll (original)
> +++ llvm/trunk/test/Transforms/ObjCARC/no-objc-arc-exceptions.ll (removed)
> @@ -1,123 +0,0 @@
> -; RUN: opt -S -objc-arc < %s | FileCheck %s
> -
> -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> -%struct.__block_byref_x = type { i8*, %struct.__block_byref_x*, i32, i32, i32 }
> -%struct.__block_descriptor = type { i64, i64 }
> - at _NSConcreteStackBlock = external global i8*
> - at __block_descriptor_tmp = external hidden constant { i64, i64, i8*, i8*, i8*, i8* }
> -
> -; The optimizer should make use of the !clang.arc.no_objc_arc_exceptions
> -; metadata and eliminate the retainBlock+release pair here.
> -; rdar://10803830.
> -
> -; CHECK-LABEL: define void @test0(
> -; CHECK-NOT: @objc
> -; CHECK: }
> -define void @test0() {
> -entry:
> -  %x = alloca %struct.__block_byref_x, align 8
> -  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
> -  %byref.isa = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 0
> -  store i8* null, i8** %byref.isa, align 8
> -  %byref.forwarding = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 1
> -  store %struct.__block_byref_x* %x, %struct.__block_byref_x** %byref.forwarding, align 8
> -  %byref.flags = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 2
> -  store i32 0, i32* %byref.flags, align 8
> -  %byref.size = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 3
> -  store i32 32, i32* %byref.size, align 4
> -  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 0
> -  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
> -  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 1
> -  store i32 1107296256, i32* %block.flags, align 8
> -  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 2
> -  store i32 0, i32* %block.reserved, align 4
> -  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 3
> -  store i8* bitcast (void (i8*)* @__foo_block_invoke_0 to i8*), i8** %block.invoke, align 8
> -  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 4
> -  store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
> -  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 5
> -  %t1 = bitcast %struct.__block_byref_x* %x to i8*
> -  store i8* %t1, i8** %block.captured, align 8
> -  %t2 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block to i8*
> -  %t3 = call i8* @objc_retainBlock(i8* %t2) nounwind, !clang.arc.copy_on_escape !4
> -  %t4 = getelementptr inbounds i8* %t3, i64 16
> -  %t5 = bitcast i8* %t4 to i8**
> -  %t6 = load i8** %t5, align 8
> -  %t7 = bitcast i8* %t6 to void (i8*)*
> -  invoke void %t7(i8* %t3)
> -          to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !4
> -
> -invoke.cont:                                      ; preds = %entry
> -  call void @objc_release(i8* %t3) nounwind, !clang.imprecise_release !4
> -  call void @_Block_object_dispose(i8* %t1, i32 8)
> -  ret void
> -
> -lpad:                                             ; preds = %entry
> -  %t8 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
> -          cleanup
> -  call void @_Block_object_dispose(i8* %t1, i32 8)
> -  resume { i8*, i32 } %t8
> -}
> -
> -; There is no !clang.arc.no_objc_arc_exceptions metadata here, so the optimizer
> -; shouldn't eliminate anything, but *CAN* strength reduce the objc_retainBlock
> -; to an objc_retain.
> -
> -; CHECK-LABEL: define void @test0_no_metadata(
> -; CHECK: call i8* @objc_retain(
> -; CHECK: invoke
> -; CHECK: call void @objc_release(
> -; CHECK: }
> -define void @test0_no_metadata() {
> -entry:
> -  %x = alloca %struct.__block_byref_x, align 8
> -  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
> -  %byref.isa = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 0
> -  store i8* null, i8** %byref.isa, align 8
> -  %byref.forwarding = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 1
> -  store %struct.__block_byref_x* %x, %struct.__block_byref_x** %byref.forwarding, align 8
> -  %byref.flags = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 2
> -  store i32 0, i32* %byref.flags, align 8
> -  %byref.size = getelementptr inbounds %struct.__block_byref_x* %x, i64 0, i32 3
> -  store i32 32, i32* %byref.size, align 4
> -  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 0
> -  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
> -  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 1
> -  store i32 1107296256, i32* %block.flags, align 8
> -  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 2
> -  store i32 0, i32* %block.reserved, align 4
> -  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 3
> -  store i8* bitcast (void (i8*)* @__foo_block_invoke_0 to i8*), i8** %block.invoke, align 8
> -  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 4
> -  store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
> -  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 5
> -  %t1 = bitcast %struct.__block_byref_x* %x to i8*
> -  store i8* %t1, i8** %block.captured, align 8
> -  %t2 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block to i8*
> -  %t3 = call i8* @objc_retainBlock(i8* %t2) nounwind, !clang.arc.copy_on_escape !4
> -  %t4 = getelementptr inbounds i8* %t3, i64 16
> -  %t5 = bitcast i8* %t4 to i8**
> -  %t6 = load i8** %t5, align 8
> -  %t7 = bitcast i8* %t6 to void (i8*)*
> -  invoke void %t7(i8* %t3)
> -          to label %invoke.cont unwind label %lpad
> -
> -invoke.cont:                                      ; preds = %entry
> -  call void @objc_release(i8* %t3) nounwind, !clang.imprecise_release !4
> -  call void @_Block_object_dispose(i8* %t1, i32 8)
> -  ret void
> -
> -lpad:                                             ; preds = %entry
> -  %t8 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
> -          cleanup
> -  call void @_Block_object_dispose(i8* %t1, i32 8)
> -  resume { i8*, i32 } %t8
> -}
> -
> -declare i8* @objc_retainBlock(i8*)
> -declare void @objc_release(i8*)
> -declare void @_Block_object_dispose(i8*, i32)
> -declare i32 @__objc_personality_v0(...)
> -declare void @__foo_block_invoke_0(i8* nocapture) uwtable ssp
> -
> -!4 = metadata !{}
> 
> Removed: llvm/trunk/test/Transforms/ObjCARC/retain-block-alloca.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/retain-block-alloca.ll?rev=189868&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/ObjCARC/retain-block-alloca.ll (original)
> +++ llvm/trunk/test/Transforms/ObjCARC/retain-block-alloca.ll (removed)
> @@ -1,94 +0,0 @@
> -; RUN: opt -S -objc-arc < %s | FileCheck %s
> -; rdar://10209613
> -
> -%0 = type opaque
> -%struct.__block_descriptor = type { i64, i64 }
> -
> - at _NSConcreteStackBlock = external global i8*
> - at __block_descriptor_tmp = external hidden constant { i64, i64, i8*, i8*, i8*, i8* }
> -@"\01L_OBJC_SELECTOR_REFERENCES_" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
> -
> -; CHECK-LABEL: define void @test(
> -; CHECK: %3 = call i8* @objc_retainBlock(i8* %2) [[NUW:#[0-9]+]]
> -; CHECK: @objc_msgSend
> -; CHECK-NEXT: @objc_release(i8* %3)
> -define void @test(%0* %array) uwtable {
> -entry:
> -  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>, align 8
> -  %0 = bitcast %0* %array to i8*
> -  %1 = tail call i8* @objc_retain(i8* %0) nounwind
> -  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 0
> -  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
> -  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 1
> -  store i32 1107296256, i32* %block.flags, align 8
> -  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 2
> -  store i32 0, i32* %block.reserved, align 4
> -  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 3
> -  store i8* bitcast (void (i8*)* @__test_block_invoke_0 to i8*), i8** %block.invoke, align 8
> -  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 4
> -  store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
> -  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 5
> -  store %0* %array, %0** %block.captured, align 8
> -  %2 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block to i8*
> -  %3 = call i8* @objc_retainBlock(i8* %2) nounwind
> -  %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
> -  call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* %0, i8* %tmp2, i8* %3)
> -  call void @objc_release(i8* %3) nounwind
> -  %strongdestroy = load %0** %block.captured, align 8
> -  %4 = bitcast %0* %strongdestroy to i8*
> -  call void @objc_release(i8* %4) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Same as test, but the objc_retainBlock has a clang.arc.copy_on_escape
> -; tag so it's safe to delete.
> -
> -; CHECK-LABEL: define void @test_with_COE(
> -; CHECK-NOT: @objc_retainBlock
> -; CHECK: @objc_msgSend
> -; CHECK: @objc_release
> -; CHECK-NOT: @objc_release
> -; CHECK: }
> -define void @test_with_COE(%0* %array) uwtable {
> -entry:
> -  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>, align 8
> -  %0 = bitcast %0* %array to i8*
> -  %1 = tail call i8* @objc_retain(i8* %0) nounwind
> -  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 0
> -  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
> -  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 1
> -  store i32 1107296256, i32* %block.flags, align 8
> -  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 2
> -  store i32 0, i32* %block.reserved, align 4
> -  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 3
> -  store i8* bitcast (void (i8*)* @__test_block_invoke_0 to i8*), i8** %block.invoke, align 8
> -  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 4
> -  store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
> -  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 5
> -  store %0* %array, %0** %block.captured, align 8
> -  %2 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block to i8*
> -  %3 = call i8* @objc_retainBlock(i8* %2) nounwind, !clang.arc.copy_on_escape !0
> -  %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
> -  call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* %0, i8* %tmp2, i8* %3)
> -  call void @objc_release(i8* %3) nounwind
> -  %strongdestroy = load %0** %block.captured, align 8
> -  %4 = bitcast %0* %strongdestroy to i8*
> -  call void @objc_release(i8* %4) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -declare i8* @objc_retain(i8*)
> -
> -declare void @__test_block_invoke_0(i8* nocapture) uwtable
> -
> -declare i8* @objc_retainBlock(i8*)
> -
> -declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
> -
> -declare void @objc_release(i8*)
> -
> -; CHECK: attributes #0 = { uwtable }
> -; CHECK: attributes #1 = { nonlazybind }
> -; CHECK: attributes [[NUW]] = { nounwind }
> -
> -!0 = metadata !{}
> 
> Removed: llvm/trunk/test/Transforms/ObjCARC/retain-block-escape-analysis.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/retain-block-escape-analysis.ll?rev=189868&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/ObjCARC/retain-block-escape-analysis.ll (original)
> +++ llvm/trunk/test/Transforms/ObjCARC/retain-block-escape-analysis.ll (removed)
> @@ -1,215 +0,0 @@
> -; RUN: opt -S -objc-arc < %s | FileCheck %s
> -
> -declare i8* @objc_retain(i8*) nonlazybind
> -declare void @objc_release(i8*) nonlazybind
> -declare i8* @objc_retainBlock(i8*)
> -
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -; Use by an instruction which copies the value is an escape if the             ;
> -; result is an escape. The current instructions with this property are:        ;
> -;                                                                              ;
> -; 1. BitCast.                                                                  ;
> -; 2. GEP.                                                                      ;
> -; 3. PhiNode.                                                                  ;
> -; 4. SelectInst.                                                               ;
> -;                                                                              ;
> -; Make sure that such instructions do not confuse the optimizer into removing  ;
> -; an objc_retainBlock that is needed.                                          ;
> -;                                                                              ;
> -; rdar://13273675. (With extra test cases to handle bitcast, phi, and select.  ;
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -
> -define void @bitcasttest(i8* %storage, void (...)* %block)  {
> -; CHECK-LABEL: define void @bitcasttest(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %storage to void (...)**
> -  %t5 = bitcast i8* %t3 to void (...)*
> -  store void (...)* %t5, void (...)** %t4, align 8
> -; CHECK: call void @objc_release
> -  call void @objc_release(i8* %t1)
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @bitcasttest_a(i8* %storage, void (...)* %block)  {
> -; CHECK-LABEL: define void @bitcasttest_a(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK-NOT: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %storage to void (...)**
> -  %t5 = bitcast i8* %t3 to void (...)*
> -  store void (...)* %t5, void (...)** %t4, align 8
> -; CHECK-NOT: call void @objc_release
> -  call void @objc_release(i8* %t1), !clang.imprecise_release !0
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @geptest(void (...)** %storage_array, void (...)* %block)  {
> -; CHECK-LABEL: define void @geptest(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %t3 to void (...)*
> -  
> -  %storage = getelementptr inbounds void (...)** %storage_array, i64 0
> -  
> -  store void (...)* %t4, void (...)** %storage, align 8
> -; CHECK: call void @objc_release
> -  call void @objc_release(i8* %t1)
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @geptest_a(void (...)** %storage_array, void (...)* %block)  {
> -; CHECK-LABEL: define void @geptest_a(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK-NOT: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %t3 to void (...)*
> -  
> -  %storage = getelementptr inbounds void (...)** %storage_array, i64 0
> -  
> -  store void (...)* %t4, void (...)** %storage, align 8
> -; CHECK-NOT: call void @objc_release
> -  call void @objc_release(i8* %t1), !clang.imprecise_release !0
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @selecttest(void (...)** %store1, void (...)** %store2,
> -                        void (...)* %block) {
> -; CHECK-LABEL: define void @selecttest(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %t3 to void (...)*
> -  %store = select i1 undef, void (...)** %store1, void (...)** %store2
> -  store void (...)* %t4, void (...)** %store, align 8
> -; CHECK: call void @objc_release
> -  call void @objc_release(i8* %t1)
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @selecttest_a(void (...)** %store1, void (...)** %store2,
> -                          void (...)* %block) {
> -; CHECK-LABEL: define void @selecttest_a(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK-NOT: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %t3 to void (...)*
> -  %store = select i1 undef, void (...)** %store1, void (...)** %store2
> -  store void (...)* %t4, void (...)** %store, align 8
> -; CHECK-NOT: call void @objc_release
> -  call void @objc_release(i8* %t1), !clang.imprecise_release !0
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @phinodetest(void (...)** %storage1,
> -                         void (...)** %storage2,
> -                         void (...)* %block) {
> -; CHECK-LABEL: define void @phinodetest(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %t3 to void (...)*
> -  br i1 undef, label %store1_set, label %store2_set
> -; CHECK: store1_set:
> -
> -store1_set:
> -  br label %end
> -
> -store2_set:
> -  br label %end
> -
> -end:
> -; CHECK: end:
> -  %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set]
> -  store void (...)* %t4, void (...)** %storage, align 8
> -; CHECK: call void @objc_release
> -  call void @objc_release(i8* %t1)
> -  ret void
> -; CHECK: }
> -}
> -
> -define void @phinodetest_a(void (...)** %storage1,
> -                           void (...)** %storage2,
> -                           void (...)* %block) {
> -; CHECK-LABEL: define void @phinodetest_a(
> -entry:
> -  %t1 = bitcast void (...)* %block to i8*
> -; CHECK-NOT: tail call i8* @objc_retain
> -  %t2 = tail call i8* @objc_retain(i8* %t1)
> -; CHECK: tail call i8* @objc_retainBlock
> -  %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
> -  %t4 = bitcast i8* %t3 to void (...)*
> -  br i1 undef, label %store1_set, label %store2_set
> -
> -store1_set:
> -  br label %end
> -
> -store2_set:
> -  br label %end
> -
> -end:
> -  %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set]
> -  store void (...)* %t4, void (...)** %storage, align 8
> -; CHECK-NOT: call void @objc_release
> -  call void @objc_release(i8* %t1), !clang.imprecise_release !0
> -  ret void
> -}
> -
> -
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -; This test makes sure that we do not hang clang when visiting a use ;
> -; cycle caused by phi nodes during objc-arc analysis. *NOTE* This    ;
> -; test case looks a little convoluted since it was produced by	     ;
> -; bugpoint.							     ;
> -; 								     ;
> -; bugzilla://14551						     ;
> -; rdar://12851911						     ;
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -
> -define void @phinode_use_cycle(i8* %block) uwtable optsize ssp {
> -; CHECK-LABEL: define void @phinode_use_cycle(i8* %block)
> -entry:
> -  br label %for.body
> -
> -for.body:                                         ; preds = %if.then, %for.body, %entry
> -  %block.05 = phi void (...)* [ null, %entry ], [ %1, %if.then ], [ %block.05, %for.body ]
> -  br i1 undef, label %for.body, label %if.then
> -
> -if.then:                                          ; preds = %for.body
> -  %0 = call i8* @objc_retainBlock(i8* %block), !clang.arc.copy_on_escape !0
> -  %1 = bitcast i8* %0 to void (...)*
> -  %2 = bitcast void (...)* %block.05 to i8*
> -  call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0
> -  br label %for.body
> -}
> -
> -!0 = metadata !{}
> 
> Removed: llvm/trunk/test/Transforms/ObjCARC/retain-block-load.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/retain-block-load.ll?rev=189868&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/ObjCARC/retain-block-load.ll (original)
> +++ llvm/trunk/test/Transforms/ObjCARC/retain-block-load.ll (removed)
> @@ -1,51 +0,0 @@
> -; RUN: opt -objc-arc -S < %s | FileCheck %s
> -
> -; rdar://10803830
> -; The optimizer should be able to prove that the block does not
> -; "escape", so the retainBlock+release pair can be eliminated.
> -
> -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> -
> -%struct.__block_descriptor = type { i64, i64 }
> -
> - at _NSConcreteStackBlock = external global i8*
> - at __block_descriptor_tmp = external global { i64, i64, i8*, i8* }
> -
> -; CHECK: define void @test() {
> -; CHECK-NOT: @objc
> -; CHECK: declare i8* @objc_retainBlock(i8*)
> -; CHECK: declare void @objc_release(i8*)
> -
> -define void @test() {
> -entry:
> -  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>, align 8
> -  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block, i64 0, i32 0
> -  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
> -  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block, i64 0, i32 1
> -  store i32 1073741824, i32* %block.flags, align 8
> -  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block, i64 0, i32 2
> -  store i32 0, i32* %block.reserved, align 4
> -  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block, i64 0, i32 3
> -  store i8* bitcast (i32 (i8*)* @__test_block_invoke_0 to i8*), i8** %block.invoke, align 8
> -  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block, i64 0, i32 4
> -  store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
> -  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block, i64 0, i32 5
> -  store i32 4, i32* %block.captured, align 8
> -  %tmp = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %block to i8*
> -  %tmp1 = call i8* @objc_retainBlock(i8* %tmp) nounwind, !clang.arc.copy_on_escape !0
> -  %tmp2 = getelementptr inbounds i8* %tmp1, i64 16
> -  %tmp3 = bitcast i8* %tmp2 to i8**
> -  %tmp4 = load i8** %tmp3, align 8
> -  %tmp5 = bitcast i8* %tmp4 to i32 (i8*)*
> -  %call = call i32 %tmp5(i8* %tmp1)
> -  call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -declare i32 @__test_block_invoke_0(i8* nocapture %.block_descriptor) nounwind readonly
> -
> -declare i8* @objc_retainBlock(i8*)
> -
> -declare void @objc_release(i8*)
> -
> -!0 = metadata !{}
> 
> Removed: llvm/trunk/test/Transforms/ObjCARC/retain-block.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/retain-block.ll?rev=189868&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/ObjCARC/retain-block.ll (original)
> +++ llvm/trunk/test/Transforms/ObjCARC/retain-block.ll (removed)
> @@ -1,189 +0,0 @@
> -; RUN: opt -objc-arc -S < %s | FileCheck %s
> -
> -target datalayout = "e-p:64:64:64"
> -
> -!0 = metadata !{}
> -
> -declare i8* @objc_retain(i8*)
> -declare void @callee(i8)
> -declare void @use_pointer(i8*)
> -declare void @objc_release(i8*)
> -declare i8* @objc_retainBlock(i8*)
> -declare i8* @objc_autorelease(i8*)
> -
> -; Basic retainBlock+release elimination.
> -
> -; CHECK-LABEL: define void @test0(i8* %tmp) {
> -; CHECK-NOT: @objc
> -; CHECK: }
> -define void @test0(i8* %tmp) {
> -entry:
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind, !clang.arc.copy_on_escape !0
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Same as test0, but there's no copy_on_escape metadata, so there's no
> -; optimization possible.
> -
> -; CHECK-LABEL: define void @test0_no_metadata(i8* %tmp) {
> -; CHECK: %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) [[NUW:#[0-9]+]]
> -; CHECK: tail call void @objc_release(i8* %tmp2) [[NUW]], !clang.imprecise_release !0
> -; CHECK: }
> -define void @test0_no_metadata(i8* %tmp) {
> -entry:
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Same as test0, but the pointer escapes, so there's no
> -; optimization possible.
> -
> -; CHECK-LABEL: define void @test0_escape(i8* %tmp, i8** %z) {
> -; CHECK: %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) [[NUW]], !clang.arc.copy_on_escape !0
> -; CHECK: tail call void @objc_release(i8* %tmp2) [[NUW]], !clang.imprecise_release !0
> -; CHECK: }
> -define void @test0_escape(i8* %tmp, i8** %z) {
> -entry:
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind, !clang.arc.copy_on_escape !0
> -  store i8* %tmp2, i8** %z
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Same as test0_escape, but there's no intervening call.
> -
> -; CHECK-LABEL: define void @test0_just_escape(i8* %tmp, i8** %z) {
> -; CHECK: %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) [[NUW]], !clang.arc.copy_on_escape !0
> -; CHECK: tail call void @objc_release(i8* %tmp2) [[NUW]], !clang.imprecise_release !0
> -; CHECK: }
> -define void @test0_just_escape(i8* %tmp, i8** %z) {
> -entry:
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind, !clang.arc.copy_on_escape !0
> -  store i8* %tmp2, i8** %z
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Basic nested retainBlock+release elimination.
> -
> -; CHECK: define void @test1(i8* %tmp) {
> -; CHECK-NOT: @objc
> -; CHECK: tail call i8* @objc_retain(i8* %tmp) [[NUW]]
> -; CHECK-NOT: @objc
> -; CHECK: tail call void @objc_release(i8* %tmp) [[NUW]], !clang.imprecise_release !0
> -; CHECK-NOT: @objc
> -; CHECK: }
> -define void @test1(i8* %tmp) {
> -entry:
> -  %tmp1 = tail call i8* @objc_retain(i8* %tmp) nounwind
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind, !clang.arc.copy_on_escape !0
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  tail call void @objc_release(i8* %tmp) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Same as test1, but there's no copy_on_escape metadata, so there's no
> -; retainBlock+release optimization possible. But we can still eliminate
> -; the outer retain+release.
> -
> -; CHECK-LABEL: define void @test1_no_metadata(i8* %tmp) {
> -; CHECK-NEXT: entry:
> -; CHECK-NEXT: tail call i8* @objc_retainBlock(i8* %tmp) [[NUW]]
> -; CHECK-NEXT: @use_pointer(i8* %tmp2)
> -; CHECK-NEXT: @use_pointer(i8* %tmp2)
> -; CHECK-NEXT: tail call void @objc_release(i8* %tmp2) [[NUW]], !clang.imprecise_release !0
> -; CHECK-NOT: @objc
> -; CHECK: }
> -define void @test1_no_metadata(i8* %tmp) {
> -entry:
> -  %tmp1 = tail call i8* @objc_retain(i8* %tmp) nounwind
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  tail call void @objc_release(i8* %tmp) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Same as test1, but the pointer escapes, so there's no
> -; retainBlock+release optimization possible. But we can still eliminate
> -; the outer retain+release
> -
> -; CHECK: define void @test1_escape(i8* %tmp, i8** %z) {
> -; CHECK-NEXT: entry:
> -; CHECK-NEXT: %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) [[NUW]], !clang.arc.copy_on_escape !0
> -; CHECK-NEXT: store i8* %tmp2, i8** %z
> -; CHECK-NEXT: @use_pointer(i8* %tmp2)
> -; CHECK-NEXT: @use_pointer(i8* %tmp2)
> -; CHECK-NEXT: tail call void @objc_release(i8* %tmp2) [[NUW]], !clang.imprecise_release !0
> -; CHECK-NOT: @objc
> -; CHECK: }
> -define void @test1_escape(i8* %tmp, i8** %z) {
> -entry:
> -  %tmp1 = tail call i8* @objc_retain(i8* %tmp) nounwind
> -  %tmp2 = tail call i8* @objc_retainBlock(i8* %tmp) nounwind, !clang.arc.copy_on_escape !0
> -  store i8* %tmp2, i8** %z
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @use_pointer(i8* %tmp2)
> -  tail call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
> -  tail call void @objc_release(i8* %tmp) nounwind, !clang.imprecise_release !0
> -  ret void
> -}
> -
> -; Optimize objc_retainBlock.
> -
> -; CHECK-LABEL: define void @test23(
> -; CHECK-NOT: @objc_
> -; CHECK: }
> -%block0 = type { i64, i64, i8*, i8* }
> -%block1 = type { i8**, i32, i32, i32 (%struct.__block_literal_1*)*, %block0* }
> -%struct.__block_descriptor = type { i64, i64 }
> -%struct.__block_literal_1 = type { i8**, i32, i32, i8**, %struct.__block_descriptor* }
> - at __block_holder_tmp_1 = external constant %block1
> -define void @test23() {
> -entry:
> -  %0 = call i8* @objc_retainBlock(i8* bitcast (%block1* @__block_holder_tmp_1 to i8*)) nounwind, !clang.arc.copy_on_escape !0
> -  call void @bar(i32 ()* bitcast (%block1* @__block_holder_tmp_1 to i32 ()*))
> -  call void @bar(i32 ()* bitcast (%block1* @__block_holder_tmp_1 to i32 ()*))
> -  call void @objc_release(i8* bitcast (%block1* @__block_holder_tmp_1 to i8*)) nounwind
> -  ret void
> -}
> -
> -; Don't optimize objc_retainBlock, but do strength reduce it.
> -
> -; CHECK-LABEL: define void @test3a(i8* %p) {
> -; CHECK: @objc_retain
> -; CHECK: @objc_release
> -; CHECK: }
> -define void @test3a(i8* %p) { 
> -entry:
> -  %0 = call i8* @objc_retainBlock(i8* %p) nounwind, !clang.arc.copy_on_escape !0
> -  call void @callee()
> -  call void @use_pointer(i8* %p)
> -  call void @objc_release(i8* %p) nounwind
> -  ret void
> -}
> -
> -; Don't optimize objc_retainBlock, because there's no copy_on_escape metadata.
> -
> -; CHECK-LABEL: define void @test3b(
> -; CHECK: @objc_retainBlock
> -; CHECK: @objc_release
> -; CHECK: }
> -define void @test3b() {
> -entry:
> -  %0 = call i8* @objc_retainBlock(i8* bitcast (%block1* @__block_holder_tmp_1 to i8*)) nounwind
> -  call void @bar(i32 ()* bitcast (%block1* @__block_holder_tmp_1 to i32 ()*))
> -  call void @bar(i32 ()* bitcast (%block1* @__block_holder_tmp_1 to i32 ()*))
> -  call void @objc_release(i8* bitcast (%block1* @__block_holder_tmp_1 to i8*)) nounwind
> -  ret void
> -}
> -
> -; CHECK: attributes [[NUW]] = { nounwind }
> 
> 
> _______________________________________________
> 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