Imported Upstream version 5.18.0.234

Former-commit-id: 8071ec1a8c5eaa9be24b41745add19297608001f
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-01-08 08:22:36 +00:00
parent f32dbaf0b2
commit 212f6bafcb
28494 changed files with 359 additions and 3867025 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +0,0 @@
; RUN: opt -S -objc-arc-apelim < %s | FileCheck %s
; rdar://10227311
@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }]
@x = global i32 0
declare i32 @bar() nounwind
define i32 @foo() nounwind {
entry:
ret i32 5
}
define internal void @__cxx_global_var_init() {
entry:
%call = call i32 @foo()
store i32 %call, i32* @x, align 4
ret void
}
define internal void @__dxx_global_var_init() {
entry:
%call = call i32 @bar()
store i32 %call, i32* @x, align 4
ret void
}
; CHECK: define internal void @_GLOBAL__I_x() {
; CHECK-NOT: @objc
; CHECK: }
define internal void @_GLOBAL__I_x() {
entry:
%0 = call i8* @objc_autoreleasePoolPush() nounwind
call void @__cxx_global_var_init()
call void @objc_autoreleasePoolPop(i8* %0) nounwind
ret void
}
; CHECK: define internal void @_GLOBAL__I_y() {
; CHECK: %0 = call i8* @objc_autoreleasePoolPush() [[NUW:#[0-9]+]]
; CHECK: call void @objc_autoreleasePoolPop(i8* %0) [[NUW]]
; CHECK: }
define internal void @_GLOBAL__I_y() {
entry:
%0 = call i8* @objc_autoreleasePoolPush() nounwind
call void @__dxx_global_var_init()
call void @objc_autoreleasePoolPop(i8* %0) nounwind
ret void
}
declare i8* @objc_autoreleasePoolPush()
declare void @objc_autoreleasePoolPop(i8*)
; CHECK: attributes #0 = { nounwind }

File diff suppressed because it is too large Load Diff

View File

@@ -1,435 +0,0 @@
; RUN: opt -S -objc-arc < %s | FileCheck %s
; rdar://9503416
; Detect loop boundaries and don't move retains and releases
; across them.
declare void @use_pointer(i8*)
declare i8* @objc_retain(i8*)
declare void @objc_release(i8*)
declare void @callee()
declare void @block_callee(void ()*)
; CHECK-LABEL: define void @test0(
; CHECK: call i8* @objc_retain(
; CHECK: for.body:
; CHECK-NOT: @objc
; CHECK: for.end:
; CHECK: call void @objc_release(
; CHECK: }
define void @test0(i8* %digits) {
entry:
%tmp1 = call i8* @objc_retain(i8* %digits) nounwind
call void @use_pointer(i8* %digits)
br label %for.body
for.body: ; preds = %for.body, %entry
%upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
call void @use_pointer(i8* %digits)
%inc = add i64 %upcDigitIndex.01, 1
%cmp = icmp ult i64 %inc, 12
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK-LABEL: define void @test1(
; CHECK: call i8* @objc_retain(
; CHECK: for.body:
; CHECK-NOT: @objc
; CHECK: for.end:
; CHECK: void @objc_release(
; CHECK: }
define void @test1(i8* %digits) {
entry:
%tmp1 = call i8* @objc_retain(i8* %digits) nounwind
br label %for.body
for.body: ; preds = %for.body, %entry
%upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
call void @use_pointer(i8* %digits)
call void @use_pointer(i8* %digits)
%inc = add i64 %upcDigitIndex.01, 1
%cmp = icmp ult i64 %inc, 12
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK-LABEL: define void @test2(
; CHECK: call i8* @objc_retain(
; CHECK: for.body:
; CHECK-NOT: @objc
; CHECK: for.end:
; CHECK: void @objc_release(
; CHECK: }
define void @test2(i8* %digits) {
entry:
%tmp1 = call i8* @objc_retain(i8* %digits) nounwind
br label %for.body
for.body: ; preds = %for.body, %entry
%upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
call void @use_pointer(i8* %digits)
%inc = add i64 %upcDigitIndex.01, 1
%cmp = icmp ult i64 %inc, 12
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
call void @use_pointer(i8* %digits)
call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0
ret void
}
; Delete nested retain+release pairs around loops.
; CHECK: define void @test3(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW:#[0-9]+]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @objc_release(i8* %a)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test3(i8* %a) nounwind {
entry:
%outer = call i8* @objc_retain(i8* %a) nounwind
%inner = call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
call void @callee()
store i8 0, i8* %a
br i1 undef, label %loop, label %exit
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test4(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @objc_release(i8* %a)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test4(i8* %a) nounwind {
entry:
%outer = call i8* @objc_retain(i8* %a) nounwind
%inner = call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br label %more
more:
call void @callee()
call void @callee()
store i8 0, i8* %a
br i1 undef, label %loop, label %exit
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test5(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: call void @callee()
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @use_pointer(i8* %a)
; CHECK-NEXT: call void @objc_release(i8* %a)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test5(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
call void @callee()
br label %loop
loop:
br i1 undef, label %true, label %more
true:
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @use_pointer(i8* %a)
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test6(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @use_pointer(i8* %a)
; CHECK-NEXT: call void @objc_release(i8* %a)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test6(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br i1 undef, label %true, label %more
true:
call void @callee()
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @use_pointer(i8* %a)
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test7(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: call void @callee()
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @objc_release(i8* %a)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test7(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
call void @callee()
br label %loop
loop:
br i1 undef, label %true, label %more
true:
call void @use_pointer(i8* %a)
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test8(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @objc_release(i8* %a)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test8(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br i1 undef, label %true, label %more
true:
call void @callee()
call void @use_pointer(i8* %a)
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test9(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test9(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br i1 undef, label %true, label %more
true:
call void @use_pointer(i8* %a)
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test10(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test10(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br i1 undef, label %true, label %more
true:
call void @callee()
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: define void @test11(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test11(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br i1 undef, label %true, label %more
true:
br label %more
more:
br i1 undef, label %exit, label %loop
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; Don't delete anything if they're not balanced.
; CHECK: define void @test12(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: %outer = tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: %inner = tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
; CHECK-NEXT: call void @objc_release(i8* %a) [[NUW]]
; CHECK-NEXT: call void @objc_release(i8* %a) [[NUW]], !clang.imprecise_release !0
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test12(i8* %a) nounwind {
entry:
%outer = tail call i8* @objc_retain(i8* %a) nounwind
%inner = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
br i1 undef, label %true, label %more
true:
ret void
more:
br i1 undef, label %exit, label %loop
exit:
call void @objc_release(i8* %a) nounwind
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; Do not improperly pair retains in a for loop with releases outside of a for
; loop when the proper pairing is disguised by a separate provenance represented
; by an alloca.
; rdar://12969722
; CHECK: define void @test13(i8* %a) [[NUW]] {
; CHECK: entry:
; CHECK: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK: loop:
; CHECK: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK: call void @block_callee
; CHECK: call void @objc_release(i8* %reloaded_a) [[NUW]]
; CHECK: exit:
; CHECK: call void @objc_release(i8* %a) [[NUW]]
; CHECK: }
define void @test13(i8* %a) nounwind {
entry:
%block = alloca i8*
%a1 = tail call i8* @objc_retain(i8* %a) nounwind
br label %loop
loop:
%a2 = tail call i8* @objc_retain(i8* %a) nounwind
store i8* %a, i8** %block, align 8
%casted_block = bitcast i8** %block to void ()*
call void @block_callee(void ()* %casted_block)
%reloaded_a = load i8*, i8** %block, align 8
call void @objc_release(i8* %reloaded_a) nounwind, !clang.imprecise_release !0
br i1 undef, label %loop, label %exit
exit:
call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
; CHECK: attributes [[NUW]] = { nounwind }
!0 = !{}

View File

@@ -1,45 +0,0 @@
; RUN: opt -objc-arc -S %s | FileCheck %s
%0 = type opaque
; Make sure ARC optimizer doesn't sink @obj_retain past @clang.arc.use.
; CHECK: call i8* @objc_retain(
; CHECK: call void (...) @clang.arc.use(
; CHECK: call i8* @objc_retain(
; CHECK: call void (...) @clang.arc.use(
define void @runTest() local_unnamed_addr {
%1 = alloca %0*, align 8
%2 = alloca %0*, align 8
%3 = tail call %0* @foo0()
%4 = bitcast %0* %3 to i8*
%5 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %4)
store %0* %3, %0** %1, align 8
call void @foo1(%0** nonnull %1)
%6 = load %0*, %0** %1, align 8
%7 = bitcast %0* %6 to i8*
%8 = call i8* @objc_retain(i8* %7)
call void (...) @clang.arc.use(%0* %3)
call void @objc_release(i8* %4)
store %0* %6, %0** %2, align 8
call void @foo1(%0** nonnull %2)
%9 = load %0*, %0** %2, align 8
%10 = bitcast %0* %9 to i8*
%11 = call i8* @objc_retain(i8* %10)
call void (...) @clang.arc.use(%0* %6)
%tmp1 = load %0*, %0** %2, align 8
call void @objc_release(i8* %7)
call void @foo2(%0* %9)
call void @objc_release(i8* %10)
ret void
}
declare %0* @foo0() local_unnamed_addr
declare void @foo1(%0**) local_unnamed_addr
declare void @foo2(%0*) local_unnamed_addr
declare i8* @objc_retainAutoreleasedReturnValue(i8*) local_unnamed_addr
declare i8* @objc_retain(i8*) local_unnamed_addr
declare void @clang.arc.use(...) local_unnamed_addr
declare void @objc_release(i8*) local_unnamed_addr

View File

@@ -1,53 +0,0 @@
; RUN: opt -S -objc-arc-apelim < %s | FileCheck %s
; See PR26774
@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }]
@x = global i32 0
declare i32 @bar() nounwind
define linkonce_odr i32 @foo() nounwind {
entry:
ret i32 5
}
define internal void @__cxx_global_var_init() {
entry:
%call = call i32 @foo()
store i32 %call, i32* @x, align 4
ret void
}
define internal void @__dxx_global_var_init() {
entry:
%call = call i32 @bar()
store i32 %call, i32* @x, align 4
ret void
}
; CHECK-LABEL: define internal void @_GLOBAL__I_x() {
define internal void @_GLOBAL__I_x() {
entry:
; CHECK: call i8* @objc_autoreleasePoolPush()
; CHECK-NEXT: call void @__cxx_global_var_init()
; CHECK-NEXT: call void @objc_autoreleasePoolPop(i8* %0)
; CHECK-NEXT: ret void
%0 = call i8* @objc_autoreleasePoolPush() nounwind
call void @__cxx_global_var_init()
call void @objc_autoreleasePoolPop(i8* %0) nounwind
ret void
}
define internal void @_GLOBAL__I_y() {
entry:
%0 = call i8* @objc_autoreleasePoolPush() nounwind
call void @__dxx_global_var_init()
call void @objc_autoreleasePoolPop(i8* %0) nounwind
ret void
}
declare i8* @objc_autoreleasePoolPush()
declare void @objc_autoreleasePoolPop(i8*)

View File

@@ -1,30 +0,0 @@
; RUN: opt -S < %s -objc-arc-expand -objc-arc-contract | FileCheck %s
; Don't crash. Reproducer for a use_iterator bug from r203364.
; rdar://problem/16333235
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin13.2.0"
%struct = type { i8*, i8* }
; CHECK-LABEL: @foo() {
define internal i8* @foo() {
entry:
%call = call i8* @bar()
; CHECK: %retained1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call)
%retained1 = call i8* @objc_retain(i8* %call)
%isnull = icmp eq i8* %retained1, null
br i1 %isnull, label %cleanup, label %if.end
if.end:
; CHECK: %retained2 = call i8* @objc_retain(i8* %retained1)
%retained2 = call i8* @objc_retain(i8* %retained1)
br label %cleanup
cleanup:
%retval = phi i8* [ %retained2, %if.end ], [ null, %entry ]
ret i8* %retval
}
declare i8* @bar()
declare extern_weak i8* @objc_retain(i8*)

View File

@@ -1,45 +0,0 @@
; RUN: opt -S -objc-arc-contract < %s | FileCheck %s
; CHECK-LABEL: define void @foo() {
; CHECK: %call = tail call i32* @qux()
; CHECK-NEXT: %tcall = bitcast i32* %call to i8*
; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for return value optimization", ""()
; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
; CHECK: }
define void @foo() {
entry:
%call = tail call i32* @qux()
%tcall = bitcast i32* %call to i8*
%0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tcall) nounwind
tail call void @bar(i8* %0)
ret void
}
; CHECK-LABEL: define void @foo2() {
; CHECK: %call = tail call i32* @qux()
; CHECK-NEXT: %tcall = bitcast i32* %call to i8*
; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for return value optimization", ""()
; CHECK-NEXT: %0 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
; CHECK: }
define void @foo2() {
entry:
%call = tail call i32* @qux()
%tcall = bitcast i32* %call to i8*
%0 = tail call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %tcall) nounwind
tail call void @bar(i8* %0)
ret void
}
declare i32* @qux()
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
declare void @bar(i8*)
!clang.arc.retainAutoreleasedReturnValueMarker = !{!0}
!0 = !{!"mov\09r7, r7\09\09@ marker for return value optimization"}
; CHECK: attributes [[NUW]] = { nounwind }

View File

@@ -1,18 +0,0 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
declare i8* @objc_autoreleaseReturnValue(i8*)
declare i8* @foo1()
; Check that ARC contraction replaces the function return with the value
; returned by @objc_autoreleaseReturnValue.
; CHECK: %[[V0:[0-9]+]] = tail call i8* @objc_autoreleaseReturnValue(
; CHECK: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to i32*
; CHECK: ret i32* %[[V1]]
define i32* @autoreleaseRVTailCall() {
%1 = call i8* @foo1()
%2 = bitcast i8* %1 to i32*
%3 = tail call i8* @objc_autoreleaseReturnValue(i8* %1)
ret i32* %2
}

View File

@@ -1,31 +0,0 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
; CHECK: tail call void @objc_storeStrong(i8**
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"
target triple = "x86_64-apple-darwin11.0.0"
%0 = type opaque
%1 = type opaque
@"OBJC_IVAR_$_Controller.preferencesController" = external global i64, section "__DATA, __objc_const", align 8
declare i8* @objc_retain(i8*)
declare void @objc_release(i8*)
define hidden void @y(%0* nocapture %self, %1* %preferencesController) nounwind {
entry:
%ivar = load i64, i64* @"OBJC_IVAR_$_Controller.preferencesController", align 8
%tmp = bitcast %0* %self to i8*
%add.ptr = getelementptr inbounds i8, i8* %tmp, i64 %ivar
%tmp1 = bitcast i8* %add.ptr to %1**
%tmp2 = load %1*, %1** %tmp1, align 8
%tmp3 = bitcast %1* %preferencesController to i8*
%tmp4 = tail call i8* @objc_retain(i8* %tmp3) nounwind
%tmp5 = bitcast %1* %tmp2 to i8*
tail call void @objc_release(i8* %tmp5) nounwind
%tmp6 = bitcast i8* %tmp4 to %1*
store %1* %tmp6, %1** %tmp1, align 8
ret void
}

View File

@@ -1,261 +0,0 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64"
declare i8* @objc_retain(i8*)
declare void @objc_release(i8*)
declare void @use_pointer(i8*)
@x = external global i8*
; CHECK-LABEL: define void @test0(
; CHECK: entry:
; CHECK-NEXT: tail call void @objc_storeStrong(i8** @x, i8* %p) [[NUW:#[0-9]+]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test0(i8* %p) {
entry:
%0 = tail call i8* @objc_retain(i8* %p) nounwind
%tmp = load i8*, i8** @x, align 8
store i8* %0, i8** @x, align 8
tail call void @objc_release(i8* %tmp) nounwind
ret void
}
; Don't do this if the load is volatile.
; CHECK-LABEL: define void @test1(i8* %p) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK-NEXT: %tmp = load volatile i8*, i8** @x, align 8
; CHECK-NEXT: store i8* %0, i8** @x, align 8
; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test1(i8* %p) {
entry:
%0 = tail call i8* @objc_retain(i8* %p) nounwind
%tmp = load volatile i8*, i8** @x, align 8
store i8* %0, i8** @x, align 8
tail call void @objc_release(i8* %tmp) nounwind
ret void
}
; Don't do this if the store is volatile.
; CHECK-LABEL: define void @test2(i8* %p) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8
; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8
; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test2(i8* %p) {
entry:
%0 = tail call i8* @objc_retain(i8* %p) nounwind
%tmp = load i8*, i8** @x, align 8
store volatile i8* %0, i8** @x, align 8
tail call void @objc_release(i8* %tmp) nounwind
ret void
}
; Don't do this if there's a use of the old pointer value between the store
; and the release.
; CHECK-LABEL: define void @test3(i8* %newValue) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) [[NUW]]
; CHECK-NEXT: %x1 = load i8*, i8** @x, align 8
; CHECK-NEXT: store i8* %x0, i8** @x, align 8
; CHECK-NEXT: tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0
; CHECK-NEXT: tail call void @objc_release(i8* %x1) [[NUW]], !clang.imprecise_release !0
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test3(i8* %newValue) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
%x1 = load i8*, i8** @x, align 8
store i8* %newValue, i8** @x, align 8
tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
ret void
}
; Like test3, but with an icmp use instead of a call, for good measure.
; CHECK-LABEL: define i1 @test4(i8* %newValue, i8* %foo) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) [[NUW]]
; CHECK-NEXT: %x1 = load i8*, i8** @x, align 8
; CHECK-NEXT: store i8* %x0, i8** @x, align 8
; CHECK-NEXT: %t = icmp eq i8* %x1, %foo
; CHECK-NEXT: tail call void @objc_release(i8* %x1) [[NUW]], !clang.imprecise_release !0
; CHECK-NEXT: ret i1 %t
; CHECK-NEXT: }
define i1 @test4(i8* %newValue, i8* %foo) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
%x1 = load i8*, i8** @x, align 8
store i8* %newValue, i8** @x, align 8
%t = icmp eq i8* %x1, %foo
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
ret i1 %t
}
; Do form an objc_storeStrong here, because the use is before the store.
; CHECK-LABEL: define i1 @test5(i8* %newValue, i8* %foo) {
; CHECK: %t = icmp eq i8* %x1, %foo
; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) [[NUW]]
; CHECK: }
define i1 @test5(i8* %newValue, i8* %foo) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
%x1 = load i8*, i8** @x, align 8
%t = icmp eq i8* %x1, %foo
store i8* %newValue, i8** @x, align 8
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
ret i1 %t
}
; Like test5, but the release is before the store.
; CHECK-LABEL: define i1 @test6(i8* %newValue, i8* %foo) {
; CHECK: %t = icmp eq i8* %x1, %foo
; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) [[NUW]]
; CHECK: }
define i1 @test6(i8* %newValue, i8* %foo) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
%x1 = load i8*, i8** @x, align 8
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
%t = icmp eq i8* %x1, %foo
store i8* %newValue, i8** @x, align 8
ret i1 %t
}
; Like test0, but there's no store, so don't form an objc_storeStrong.
; CHECK-LABEL: define void @test7(
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8
; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test7(i8* %p) {
entry:
%0 = tail call i8* @objc_retain(i8* %p) nounwind
%tmp = load i8*, i8** @x, align 8
tail call void @objc_release(i8* %tmp) nounwind
ret void
}
; Like test0, but there's no retain, so don't form an objc_storeStrong.
; CHECK-LABEL: define void @test8(
; CHECK-NEXT: entry:
; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8
; CHECK-NEXT: store i8* %p, i8** @x, align 8
; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test8(i8* %p) {
entry:
%tmp = load i8*, i8** @x, align 8
store i8* %p, i8** @x, align 8
tail call void @objc_release(i8* %tmp) nounwind
ret void
}
; Make sure that we properly handle release that *may* release our new
; value in between the retain and the store. We need to be sure that
; this we can safely move the retain to the store. This specific test
; makes sure that we properly handled a release of an unrelated
; pointer.
;
; CHECK-LABEL: define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
; CHECK-NOT: objc_storeStrong
define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
tail call void @objc_release(i8* %unrelated_ptr) nounwind, !clang.imprecise_release !0
%x1 = load i8*, i8** @x, align 8
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
%t = icmp eq i8* %x1, %foo
store i8* %newValue, i8** @x, align 8
ret i1 %t
}
; Make sure that we don't perform the optimization when we just have a call.
;
; CHECK-LABEL: define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
; CHECK-NOT: objc_storeStrong
define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
call void @use_pointer(i8* %unrelated_ptr)
%x1 = load i8*, i8** @x, align 8
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
%t = icmp eq i8* %x1, %foo
store i8* %newValue, i8** @x, align 8
ret i1 %t
}
; Make sure we form the store strong if the use in between the retain
; and the store does not touch reference counts.
; CHECK-LABEL: define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
; CHECK: objc_storeStrong
define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
%t = icmp eq i8* %newValue, %foo
%x1 = load i8*, i8** @x, align 8
tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0
store i8* %newValue, i8** @x, align 8
ret i1 %t
}
; Make sure that we form the store strong even if there are bitcasts on
; the pointers.
; CHECK-LABEL: define void @test12(
; CHECK: entry:
; CHECK-NEXT: %p16 = bitcast i8** @x to i16**
; CHECK-NEXT: %tmp16 = load i16*, i16** %p16, align 8
; CHECK-NEXT: %tmp8 = bitcast i16* %tmp16 to i8*
; CHECK-NEXT: %p32 = bitcast i8** @x to i32**
; CHECK-NEXT: %v32 = bitcast i8* %p to i32*
; CHECK-NEXT: %0 = bitcast i16** %p16 to i8**
; CHECK-NEXT: tail call void @objc_storeStrong(i8** %0, i8* %p)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test12(i8* %p) {
entry:
%retain = tail call i8* @objc_retain(i8* %p) nounwind
%p16 = bitcast i8** @x to i16**
%tmp16 = load i16*, i16** %p16, align 8
%tmp8 = bitcast i16* %tmp16 to i8*
%p32 = bitcast i8** @x to i32**
%v32 = bitcast i8* %retain to i32*
store i32* %v32, i32** %p32, align 8
tail call void @objc_release(i8* %tmp8) nounwind
ret void
}
; This used to crash.
; CHECK-LABEL: define i8* @test13(
; CHECK: tail call void @objc_storeStrong(i8** %{{.*}}, i8* %[[NEW:.*]])
; CHECK-NEXT: ret i8* %[[NEW]]
define i8* @test13(i8* %a0, i8* %a1, i8** %addr, i8* %new) {
%old = load i8*, i8** %addr, align 8
call void @objc_release(i8* %old)
%retained = call i8* @objc_retain(i8* %new)
store i8* %retained, i8** %addr, align 8
ret i8* %retained
}
!0 = !{}
; CHECK: attributes [[NUW]] = { nounwind }

View File

@@ -1,95 +0,0 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
; rdar://9511608
%0 = type opaque
%1 = type opaque
%2 = type { i64, i64 }
%4 = type opaque
declare %0* @"\01-[NSAttributedString(Terminal) pathAtIndex:effectiveRange:]"(%1*, i8* nocapture, i64, %2*) optsize
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare i8* @objc_msgSend_fixup(i8*, i8*, ...)
declare i8* @objc_msgSend(i8*, i8*, ...)
declare void @objc_release(i8*)
declare %2 @NSUnionRange(i64, i64, i64, i64) optsize
declare i8* @objc_autoreleaseReturnValue(i8*)
declare i8* @objc_autorelease(i8*)
declare i32 @__gxx_personality_sj0(...)
; Don't get in trouble on bugpointed code.
; CHECK-LABEL: define void @test0(
define void @test0() {
bb:
%tmp = bitcast %4* undef to i8*
%tmp1 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tmp) nounwind
br label %bb3
bb3: ; preds = %bb2
br i1 undef, label %bb6, label %bb4
bb4: ; preds = %bb3
switch i64 undef, label %bb5 [
i64 9223372036854775807, label %bb6
i64 0, label %bb6
]
bb5: ; preds = %bb4
br label %bb6
bb6: ; preds = %bb5, %bb4, %bb4, %bb3
%tmp7 = phi %4* [ undef, %bb5 ], [ undef, %bb4 ], [ undef, %bb3 ], [ undef, %bb4 ]
unreachable
}
; When rewriting operands for a phi which has multiple operands
; for the same block, use the exactly same value in each block.
; CHECK-LABEL: define void @test1(
; CHECK: %0 = bitcast i8* %tmp3 to %0*
; CHECK: br i1 undef, label %bb7, label %bb7
; CHECK: bb7:
; CHECK: %tmp8 = phi %0* [ %0, %bb ], [ %0, %bb ]
; CHECK: }
define void @test1() {
bb:
%tmp = tail call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to %0* ()*)()
%tmp2 = bitcast %0* %tmp to i8*
%tmp3 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tmp2) nounwind
br i1 undef, label %bb7, label %bb7
bb7: ; preds = %bb6, %bb6, %bb5
%tmp8 = phi %0* [ %tmp, %bb ], [ %tmp, %bb ]
unreachable
}
; When looking for the defining instruction for an objc_retainAutoreleasedReturnValue
; call, handle the case where it's an invoke in a different basic block.
; rdar://11714057
; CHECK: define void @_Z6doTestP8NSString() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
; CHECK: invoke.cont: ; preds = %entry
; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue", ""()
; CHECK-NEXT: %tmp = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) [[NUW:#[0-9]+]]
; CHECK: }
define void @_Z6doTestP8NSString() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
entry:
%call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* ()*)()
to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %entry
%tmp = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
unreachable
lpad: ; preds = %entry
%tmp1 = landingpad { i8*, i32 }
cleanup
resume { i8*, i32 } undef
}
!clang.arc.retainAutoreleasedReturnValueMarker = !{!0}
!0 = !{!"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"}
; CHECK: attributes #0 = { optsize }
; CHECK: attributes [[NUW]] = { nounwind }

View File

@@ -1,232 +0,0 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64"
declare i8* @objc_retain(i8*)
declare void @objc_release(i8*)
declare i8* @objc_autorelease(i8*)
declare i8* @objc_autoreleaseReturnValue(i8*)
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare void @use_pointer(i8*)
declare i8* @returner()
declare void @callee()
; CHECK-LABEL: define void @test0(
; CHECK: call void @use_pointer(i8* %0)
; CHECK: }
define void @test0(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retain(i8* %x) nounwind
call void @use_pointer(i8* %x)
ret void
}
; CHECK-LABEL: define void @test1(
; CHECK: call void @use_pointer(i8* %0)
; CHECK: }
define void @test1(i8* %x) nounwind {
entry:
%0 = call i8* @objc_autorelease(i8* %x) nounwind
call void @use_pointer(i8* %x)
ret void
}
; Merge objc_retain and objc_autorelease into objc_retainAutorelease.
; CHECK-LABEL: define void @test2(
; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) [[NUW:#[0-9]+]]
; CHECK: }
define void @test2(i8* %x) nounwind {
entry:
%0 = tail call i8* @objc_retain(i8* %x) nounwind
call i8* @objc_autorelease(i8* %0) nounwind
call void @use_pointer(i8* %x)
ret void
}
; Same as test2 but the value is returned. Do an RV optimization.
; CHECK-LABEL: define i8* @test2b(
; CHECK: tail call i8* @objc_retainAutoreleaseReturnValue(i8* %x) [[NUW]]
; CHECK: }
define i8* @test2b(i8* %x) nounwind {
entry:
%0 = tail call i8* @objc_retain(i8* %x) nounwind
tail call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind
ret i8* %x
}
; Merge a retain,autorelease pair around a call.
; CHECK-LABEL: define void @test3(
; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) [[NUW]]
; CHECK: @use_pointer(i8* %0)
; CHECK: }
define void @test3(i8* %x, i64 %n) {
entry:
tail call i8* @objc_retain(i8* %x) nounwind
call void @use_pointer(i8* %x)
call i8* @objc_autorelease(i8* %x) nounwind
ret void
}
; Trivial retain,autorelease pair with intervening call, but it's post-dominated
; by another release. The retain and autorelease can be merged.
; CHECK-LABEL: define void @test4(
; CHECK-NEXT: entry:
; CHECK-NEXT: @objc_retainAutorelease(i8* %x) [[NUW]]
; CHECK-NEXT: @use_pointer
; CHECK-NEXT: @objc_release
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test4(i8* %x, i64 %n) {
entry:
tail call i8* @objc_retain(i8* %x) nounwind
call void @use_pointer(i8* %x)
call i8* @objc_autorelease(i8* %x) nounwind
tail call void @objc_release(i8* %x) nounwind
ret void
}
; Don't merge retain and autorelease if they're not control-equivalent.
; CHECK-LABEL: define void @test5(
; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK: true:
; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]]
; CHECK: }
define void @test5(i8* %p, i1 %a) {
entry:
tail call i8* @objc_retain(i8* %p) nounwind
br i1 %a, label %true, label %false
true:
call i8* @objc_autorelease(i8* %p) nounwind
call void @use_pointer(i8* %p)
ret void
false:
ret void
}
; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
; an objc_autorelease.
; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
; objc_retainAutoreleasedReturnValueAutorelease and merge
; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
; Those entrypoints don't exist yet though.
; CHECK-LABEL: define i8* @test6(
; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %p) [[NUW]]
; CHECK: %t = tail call i8* @objc_autoreleaseReturnValue(i8* %1) [[NUW]]
; CHECK: }
define i8* @test6() {
%p = call i8* @returner()
tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p) nounwind
%t = tail call i8* @objc_autoreleaseReturnValue(i8* %p) nounwind
call void @use_pointer(i8* %t)
ret i8* %t
}
; Don't spoil the RV optimization.
; CHECK: define i8* @test7(i8* %p)
; CHECK: tail call i8* @objc_retain(i8* %p)
; CHECK: call void @use_pointer(i8* %1)
; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %1)
; CHECK: ret i8* %2
; CHECK-NEXT: }
define i8* @test7(i8* %p) {
%1 = tail call i8* @objc_retain(i8* %p)
call void @use_pointer(i8* %p)
%2 = tail call i8* @objc_autoreleaseReturnValue(i8* %p)
ret i8* %p
}
; Do the return value substitution for PHI nodes too.
; CHECK-LABEL: define i8* @test8(
; CHECK: %retval = phi i8* [ %p, %if.then ], [ null, %entry ]
; CHECK: }
define i8* @test8(i1 %x, i8* %c) {
entry:
br i1 %x, label %return, label %if.then
if.then: ; preds = %entry
%p = call i8* @objc_retain(i8* %c) nounwind
br label %return
return: ; preds = %if.then, %entry
%retval = phi i8* [ %c, %if.then ], [ null, %entry ]
ret i8* %retval
}
; Kill calls to @clang.arc.use(...)
; CHECK-LABEL: define void @test9(
; CHECK-NOT: clang.arc.use
; CHECK: }
define void @test9(i8* %a, i8* %b) {
call void (...) @clang.arc.use(i8* %a, i8* %b) nounwind
ret void
}
; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand
; is a return value.
; CHECK: define void @test10()
; CHECK: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
define void @test10() {
%p = call i8* @returner()
tail call i8* @objc_retain(i8* %p) nounwind
ret void
}
; Convert objc_retain to objc_retainAutoreleasedReturnValue if its
; argument is a return value.
; CHECK-LABEL: define void @test11(
; CHECK-NEXT: %y = call i8* @returner()
; CHECK-NEXT: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) [[NUW]]
; CHECK-NEXT: ret void
define void @test11() {
%y = call i8* @returner()
tail call i8* @objc_retain(i8* %y) nounwind
ret void
}
; Don't convert objc_retain to objc_retainAutoreleasedReturnValue if its
; argument is not a return value.
; CHECK-LABEL: define void @test12(
; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test12(i8* %y) {
tail call i8* @objc_retain(i8* %y) nounwind
ret void
}
; Don't Convert objc_retain to objc_retainAutoreleasedReturnValue if it
; isn't next to the call providing its return value.
; CHECK-LABEL: define void @test13(
; CHECK-NEXT: %y = call i8* @returner()
; CHECK-NEXT: call void @callee()
; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test13() {
%y = call i8* @returner()
call void @callee()
tail call i8* @objc_retain(i8* %y) nounwind
ret void
}
declare void @clang.arc.use(...) nounwind
; CHECK: attributes [[NUW]] = { nounwind }

View File

@@ -1,59 +0,0 @@
; RUN: opt -S -objc-arc < %s | FileCheck %s
; rdar://10210274
%0 = type opaque
declare i8* @objc_retain(i8*)
declare void @objc_release(i8*)
declare i8* @objc_autoreleaseReturnValue(i8*)
; Don't delete the autorelease.
; CHECK-LABEL: define %0* @test0(
; CHECK: @objc_retain
; CHECK: .lr.ph:
; CHECK-NOT: @objc_r
; CHECK: @objc_autoreleaseReturnValue
; CHECK-NOT: @objc_
; CHECK: }
define %0* @test0(%0* %buffer) nounwind {
%1 = bitcast %0* %buffer to i8*
%2 = tail call i8* @objc_retain(i8* %1) nounwind
br i1 undef, label %.lr.ph, label %._crit_edge
.lr.ph: ; preds = %.lr.ph, %0
br i1 false, label %.lr.ph, label %._crit_edge
._crit_edge: ; preds = %.lr.ph, %0
%3 = tail call i8* @objc_retain(i8* %1) nounwind
tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
%4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
ret %0* %buffer
}
; Do delete the autorelease, even with the retain in a different block.
; CHECK-LABEL: define %0* @test1(
; CHECK-NOT: @objc
; CHECK: }
define %0* @test1() nounwind {
%buffer = call %0* @foo()
%1 = bitcast %0* %buffer to i8*
%2 = tail call i8* @objc_retain(i8* %1) nounwind
br i1 undef, label %.lr.ph, label %._crit_edge
.lr.ph: ; preds = %.lr.ph, %0
br i1 false, label %.lr.ph, label %._crit_edge
._crit_edge: ; preds = %.lr.ph, %0
%3 = tail call i8* @objc_retain(i8* %1) nounwind
tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
%4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
ret %0* %buffer
}
declare %0* @foo()
!0 = !{}

View File

@@ -1,171 +0,0 @@
; RUN: opt -objc-arc -S < %s | FileCheck %s
; rdar://11744105
; bugzilla://14584
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"
target triple = "x86_64-apple-macosx10.9.0"
%0 = type opaque
%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* }
%struct._objc_cache = type opaque
%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* }
%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
%struct._objc_method = type { i8*, i8*, i8* }
%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] }
%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32, i8** }
%struct._prop_list_t = type { i32, i32, [0 x %struct._prop_t] }
%struct._prop_t = type { i8*, i8* }
%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }
%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 }
%struct.NSConstantString = type { i32*, i32, i8*, i64 }
@"OBJC_CLASS_$_NSObject" = external global %struct._class_t
@"\01L_OBJC_CLASSLIST_REFERENCES_$_" = internal global %struct._class_t* @"OBJC_CLASS_$_NSObject", section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
@"\01L_OBJC_METH_VAR_NAME_" = internal global [4 x i8] c"new\00", section "__TEXT,__objc_methname,cstring_literals", align 1
@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
@__CFConstantStringClassReference = external global [0 x i32]
@.str = private unnamed_addr constant [11 x i8] c"Failed: %@\00", align 1
@_unnamed_cfstring_ = private constant %struct.NSConstantString { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i64 10 }, section "__DATA,__cfstring"
@"OBJC_CLASS_$_NSException" = external global %struct._class_t
@"\01L_OBJC_CLASSLIST_REFERENCES_$_1" = internal global %struct._class_t* @"OBJC_CLASS_$_NSException", section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
@.str2 = private unnamed_addr constant [4 x i8] c"Foo\00", align 1
@_unnamed_cfstring_3 = private constant %struct.NSConstantString { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring"
@"\01L_OBJC_METH_VAR_NAME_4" = internal global [14 x i8] c"raise:format:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
@"\01L_OBJC_SELECTOR_REFERENCES_5" = internal global i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_OBJC_METH_VAR_NAME_4", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
@llvm.used = appending global [6 x i8*] [i8* bitcast (%struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_" to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_" to i8*), i8* bitcast (%struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_1" to i8*), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_OBJC_METH_VAR_NAME_4", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_5" to i8*)], section "llvm.metadata"
define i32 @main() uwtable ssp personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) !dbg !5 {
entry:
%tmp = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_", align 8, !dbg !37
%tmp1 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8, !dbg !37, !invariant.load !38
%tmp2 = bitcast %struct._class_t* %tmp to i8*, !dbg !37
; CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %tmp2, i8* %tmp1)
%call = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %tmp2, i8* %tmp1), !dbg !37, !clang.arc.no_objc_arc_exceptions !38
call void @llvm.dbg.value(metadata i8* %call, metadata !25, metadata !DIExpression()), !dbg !37
; CHECK: call i8* @objc_retain(i8* %call) [[NUW:#[0-9]+]]
%tmp3 = call i8* @objc_retain(i8* %call) nounwind, !dbg !39
call void @llvm.dbg.value(metadata i8* %call, metadata !25, metadata !DIExpression()), !dbg !39
invoke fastcc void @ThrowFunc(i8* %call)
to label %eh.cont unwind label %lpad, !dbg !40, !clang.arc.no_objc_arc_exceptions !38
eh.cont: ; preds = %entry
; CHECK: call void @objc_release(i8* %call)
call void @objc_release(i8* %call) nounwind, !dbg !42, !clang.imprecise_release !38
br label %if.end, !dbg !43
lpad: ; preds = %entry
%tmp4 = landingpad { i8*, i32 }
catch i8* null, !dbg !40
%tmp5 = extractvalue { i8*, i32 } %tmp4, 0, !dbg !40
%exn.adjusted = call i8* @objc_begin_catch(i8* %tmp5) nounwind, !dbg !44
call void @llvm.dbg.value(metadata i8 0, metadata !21, metadata !DIExpression()), !dbg !46
call void @objc_end_catch(), !dbg !49, !clang.arc.no_objc_arc_exceptions !38
; CHECK: call void @objc_release(i8* %call)
call void @objc_release(i8* %call) nounwind, !dbg !42, !clang.imprecise_release !38
call void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i8* %call), !dbg !50, !clang.arc.no_objc_arc_exceptions !38
br label %if.end, !dbg !52
if.end: ; preds = %lpad, %eh.cont
call void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i8* %call), !dbg !53, !clang.arc.no_objc_arc_exceptions !38
; CHECK: call void @objc_release(i8* %call)
call void @objc_release(i8* %call) nounwind, !dbg !54, !clang.imprecise_release !38
ret i32 0, !dbg !54
}
declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
declare i8* @objc_retain(i8*) nonlazybind
declare i8* @objc_begin_catch(i8*)
declare void @objc_end_catch()
declare void @objc_exception_rethrow()
define internal fastcc void @ThrowFunc(i8* %obj) uwtable noinline ssp !dbg !27 {
entry:
%tmp = call i8* @objc_retain(i8* %obj) nounwind
call void @llvm.dbg.value(metadata i8* %obj, metadata !32, metadata !DIExpression()), !dbg !55
%tmp1 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_1", align 8, !dbg !56
%tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_5", align 8, !dbg !56, !invariant.load !38
%tmp3 = bitcast %struct._class_t* %tmp1 to i8*, !dbg !56
call void (i8*, i8*, %0*, %0*, ...) bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %0*, %0*, ...)*)(i8* %tmp3, i8* %tmp2, %0* bitcast (%struct.NSConstantString* @_unnamed_cfstring_3 to %0*), %0* bitcast (%struct.NSConstantString* @_unnamed_cfstring_3 to %0*)), !dbg !56, !clang.arc.no_objc_arc_exceptions !38
call void @objc_release(i8* %obj) nounwind, !dbg !58, !clang.imprecise_release !38
ret void, !dbg !58
}
declare i32 @__objc_personality_v0(...)
declare void @objc_release(i8*) nonlazybind
declare void @NSLog(i8*, ...)
declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
; CHECK: attributes #0 = { ssp uwtable }
; CHECK: attributes #1 = { nounwind readnone speculatable }
; CHECK: attributes #2 = { nonlazybind }
; CHECK: attributes #3 = { noinline ssp uwtable }
; CHECK: attributes [[NUW]] = { nounwind }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!33, !34, !35, !36, !61}
!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, producer: "clang version 3.3 ", isOptimized: true, runtimeVersion: 2, emissionKind: FullDebug, file: !60, enums: !1, retainedTypes: !1, globals: !1)
!1 = !{}
!5 = distinct !DISubprogram(name: "main", line: 9, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0, scopeLine: 10, file: !60, scope: !6, type: !7, variables: !11)
!6 = !DIFile(filename: "test.m", directory: "/Volumes/Files/gottesmmcab/Radar/12906997")
!7 = !DISubroutineType(types: !8)
!8 = !{!9}
!9 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !{!12, !21, !25}
!12 = !DILocalVariable(name: "obj", line: 11, scope: !13, file: !6, type: !14)
!13 = distinct !DILexicalBlock(line: 10, column: 0, file: !60, scope: !5)
!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "id", line: 11, file: !60, baseType: !15)
!15 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, file: !60, baseType: !16)
!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_object", file: !60, elements: !17)
!17 = !{!18}
!18 = !DIDerivedType(tag: DW_TAG_member, name: "isa", size: 64, file: !60, scope: !16, baseType: !19)
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, baseType: !20)
!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_class", flags: DIFlagFwdDecl, file: !60)
!21 = !DILocalVariable(name: "ok", line: 13, scope: !22, file: !6, type: !23)
!22 = distinct !DILexicalBlock(line: 12, column: 0, file: !60, scope: !13)
!23 = !DIDerivedType(tag: DW_TAG_typedef, name: "BOOL", line: 62, file: !60, baseType: !24)
!24 = !DIBasicType(tag: DW_TAG_base_type, name: "signed char", size: 8, align: 8, encoding: DW_ATE_signed_char)
!25 = !DILocalVariable(name: "obj2", line: 15, scope: !26, file: !6, type: !14)
!26 = distinct !DILexicalBlock(line: 14, column: 0, file: !60, scope: !22)
!27 = distinct !DISubprogram(name: "ThrowFunc", line: 4, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 5, file: !60, scope: !6, type: !28, variables: !31)
!28 = !DISubroutineType(types: !29)
!29 = !{null, !14}
!31 = !{!32}
!32 = !DILocalVariable(name: "obj", line: 4, arg: 1, scope: !27, file: !6, type: !14)
!33 = !{i32 1, !"Objective-C Version", i32 2}
!34 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!35 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
!36 = !{i32 4, !"Objective-C Garbage Collection", i32 0}
!37 = !DILocation(line: 11, scope: !13)
!38 = !{}
!39 = !DILocation(line: 15, scope: !26)
!40 = !DILocation(line: 17, scope: !41)
!41 = distinct !DILexicalBlock(line: 16, column: 0, file: !60, scope: !26)
!42 = !DILocation(line: 22, scope: !26)
!43 = !DILocation(line: 23, scope: !22)
!44 = !DILocation(line: 19, scope: !41)
!45 = !{i8 0}
!46 = !DILocation(line: 20, scope: !47)
!47 = distinct !DILexicalBlock(line: 19, column: 0, file: !60, scope: !48)
!48 = distinct !DILexicalBlock(line: 19, column: 0, file: !60, scope: !26)
!49 = !DILocation(line: 21, scope: !47)
!50 = !DILocation(line: 24, scope: !51)
!51 = distinct !DILexicalBlock(line: 23, column: 0, file: !60, scope: !22)
!52 = !DILocation(line: 25, scope: !51)
!53 = !DILocation(line: 27, scope: !13)
!54 = !DILocation(line: 28, scope: !13)
!55 = !DILocation(line: 4, scope: !27)
!56 = !DILocation(line: 6, scope: !57)
!57 = distinct !DILexicalBlock(line: 5, column: 0, file: !60, scope: !27)
!58 = !DILocation(line: 7, scope: !57)
!60 = !DIFile(filename: "test.m", directory: "/Volumes/Files/gottesmmcab/Radar/12906997")
!61 = !{i32 1, !"Debug Info Version", i32 3}

View File

@@ -1,134 +0,0 @@
; RUN: opt -objc-arc -S < %s | FileCheck %s
; rdar://11229925
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_weakLogNTimes = type { i8*, %struct.__block_byref_weakLogNTimes*, i32, i32, i8*, i8*, void (...)* }
%struct.__block_descriptor = type { i64, i64 }
; Don't optimize away the retainBlock, because the object's address "escapes"
; with the objc_storeWeak call.
; CHECK-LABEL: define void @test0(
; CHECK: %tmp7 = call i8* @objc_retainBlock(i8* %tmp6) [[NUW:#[0-9]+]], !clang.arc.copy_on_escape !0
; CHECK: call void @objc_release(i8* %tmp7) [[NUW]], !clang.imprecise_release !0
; CHECK: }
define void @test0() nounwind {
entry:
%weakLogNTimes = alloca %struct.__block_byref_weakLogNTimes, align 8
%block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
%byref.isa = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 0
store i8* null, i8** %byref.isa, align 8
%byref.forwarding = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 1
store %struct.__block_byref_weakLogNTimes* %weakLogNTimes, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
%byref.flags = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 2
store i32 33554432, i32* %byref.flags, align 8
%byref.size = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 3
store i32 48, i32* %byref.size, align 4
%tmp1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 4
store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_ to i8*), i8** %tmp1, align 8
%tmp2 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 5
store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_ to i8*), i8** %tmp2, align 8
%weakLogNTimes1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 6
%tmp3 = bitcast void (...)** %weakLogNTimes1 to i8**
%tmp4 = call i8* @objc_initWeak(i8** %tmp3, i8* null) nounwind
%block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 0
store i8* null, i8** %block.isa, align 8
%block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ 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* }>, <{ 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* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 3
store i8* bitcast (void (i8*, i32)* @__main_block_invoke_0 to i8*), i8** %block.invoke, align 8
%block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 4
store %struct.__block_descriptor* null, %struct.__block_descriptor** %block.descriptor, align 8
%block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 5
%tmp5 = bitcast %struct.__block_byref_weakLogNTimes* %weakLogNTimes to i8*
store i8* %tmp5, i8** %block.captured, align 8
%tmp6 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block to i8*
%tmp7 = call i8* @objc_retainBlock(i8* %tmp6) nounwind, !clang.arc.copy_on_escape !0
%tmp8 = load %struct.__block_byref_weakLogNTimes*, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
%weakLogNTimes3 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %tmp8, i64 0, i32 6
%tmp9 = bitcast void (...)** %weakLogNTimes3 to i8**
%tmp10 = call i8* @objc_storeWeak(i8** %tmp9, i8* %tmp7) nounwind
%tmp11 = getelementptr inbounds i8, i8* %tmp7, i64 16
%tmp12 = bitcast i8* %tmp11 to i8**
%tmp13 = load i8*, i8** %tmp12, align 8
%tmp14 = bitcast i8* %tmp13 to void (i8*, i32)*
call void %tmp14(i8* %tmp7, i32 10) nounwind, !clang.arc.no_objc_arc_exceptions !0
call void @objc_release(i8* %tmp7) nounwind, !clang.imprecise_release !0
call void @_Block_object_dispose(i8* %tmp5, i32 8) nounwind
call void @objc_destroyWeak(i8** %tmp3) nounwind
ret void
}
; Like test0, but it makes a regular call instead of a storeWeak call,
; so the optimization is valid.
; CHECK-LABEL: define void @test1(
; CHECK-NOT: @objc_retainBlock
; CHECK: }
define void @test1() nounwind {
entry:
%weakLogNTimes = alloca %struct.__block_byref_weakLogNTimes, align 8
%block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
%byref.isa = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 0
store i8* null, i8** %byref.isa, align 8
%byref.forwarding = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 1
store %struct.__block_byref_weakLogNTimes* %weakLogNTimes, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
%byref.flags = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 2
store i32 33554432, i32* %byref.flags, align 8
%byref.size = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 3
store i32 48, i32* %byref.size, align 4
%tmp1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 4
store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_ to i8*), i8** %tmp1, align 8
%tmp2 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 5
store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_ to i8*), i8** %tmp2, align 8
%weakLogNTimes1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 6
%tmp3 = bitcast void (...)** %weakLogNTimes1 to i8**
%tmp4 = call i8* @objc_initWeak(i8** %tmp3, i8* null) nounwind
%block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 0
store i8* null, i8** %block.isa, align 8
%block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ 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* }>, <{ 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* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 3
store i8* bitcast (void (i8*, i32)* @__main_block_invoke_0 to i8*), i8** %block.invoke, align 8
%block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 4
store %struct.__block_descriptor* null, %struct.__block_descriptor** %block.descriptor, align 8
%block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 5
%tmp5 = bitcast %struct.__block_byref_weakLogNTimes* %weakLogNTimes to i8*
store i8* %tmp5, i8** %block.captured, align 8
%tmp6 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block to i8*
%tmp7 = call i8* @objc_retainBlock(i8* %tmp6) nounwind, !clang.arc.copy_on_escape !0
%tmp8 = load %struct.__block_byref_weakLogNTimes*, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
%weakLogNTimes3 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %tmp8, i64 0, i32 6
%tmp9 = bitcast void (...)** %weakLogNTimes3 to i8**
%tmp10 = call i8* @not_really_objc_storeWeak(i8** %tmp9, i8* %tmp7) nounwind
%tmp11 = getelementptr inbounds i8, i8* %tmp7, i64 16
%tmp12 = bitcast i8* %tmp11 to i8**
%tmp13 = load i8*, i8** %tmp12, align 8
%tmp14 = bitcast i8* %tmp13 to void (i8*, i32)*
call void %tmp14(i8* %tmp7, i32 10) nounwind, !clang.arc.no_objc_arc_exceptions !0
call void @objc_release(i8* %tmp7) nounwind, !clang.imprecise_release !0
call void @_Block_object_dispose(i8* %tmp5, i32 8) nounwind
call void @objc_destroyWeak(i8** %tmp3) nounwind
ret void
}
declare void @__Block_byref_object_copy_(i8*, i8*) nounwind
declare void @__Block_byref_object_dispose_(i8*) nounwind
declare void @objc_destroyWeak(i8**)
declare i8* @objc_initWeak(i8**, i8*)
declare void @__main_block_invoke_0(i8* nocapture, i32) nounwind ssp
declare void @_Block_object_dispose(i8*, i32)
declare i8* @objc_retainBlock(i8*)
declare i8* @objc_storeWeak(i8**, i8*)
declare i8* @not_really_objc_storeWeak(i8**, i8*)
declare void @objc_release(i8*)
!0 = !{}
; CHECK: attributes [[NUW]] = { nounwind }
; CHECK: attributes #1 = { nounwind ssp }

View File

@@ -1,94 +0,0 @@
; RUN: opt -objc-arc-expand -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64"
declare i8* @objc_retain(i8*)
declare i8* @objc_autorelease(i8*)
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare i8* @objc_autoreleaseReturnValue(i8*)
declare i8* @objc_retainAutorelease(i8*)
declare i8* @objc_retainAutoreleaseReturnValue(i8*)
declare i8* @objc_retainBlock(i8*)
declare void @use_pointer(i8*)
; CHECK: define void @test_retain(i8* %x) [[NUW:#[0-9]+]] {
; CHECK: call i8* @objc_retain(i8* %x)
; CHECK: call void @use_pointer(i8* %x)
; CHECK: }
define void @test_retain(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retain(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}
; CHECK: define void @test_retainAutoreleasedReturnValue(i8* %x) [[NUW]] {
; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %x)
; CHECK: call void @use_pointer(i8* %x)
; CHECK: }
define void @test_retainAutoreleasedReturnValue(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}
; CHECK: define void @test_retainAutorelease(i8* %x) [[NUW]] {
; CHECK: call i8* @objc_retainAutorelease(i8* %x)
; CHECK: call void @use_pointer(i8* %x)
; CHECK: }
define void @test_retainAutorelease(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retainAutorelease(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}
; CHECK: define void @test_retainAutoreleaseReturnValue(i8* %x) [[NUW]] {
; CHECK: call i8* @objc_retainAutoreleaseReturnValue(i8* %x)
; CHECK: call void @use_pointer(i8* %x)
; CHECK: }
define void @test_retainAutoreleaseReturnValue(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retainAutoreleaseReturnValue(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}
; CHECK: define void @test_autorelease(i8* %x) [[NUW]] {
; CHECK: call i8* @objc_autorelease(i8* %x)
; CHECK: call void @use_pointer(i8* %x)
; CHECK: }
define void @test_autorelease(i8* %x) nounwind {
entry:
%0 = call i8* @objc_autorelease(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}
; CHECK: define void @test_autoreleaseReturnValue(i8* %x) [[NUW]] {
; CHECK: call i8* @objc_autoreleaseReturnValue(i8* %x)
; CHECK: call void @use_pointer(i8* %x)
; CHECK: }
define void @test_autoreleaseReturnValue(i8* %x) nounwind {
entry:
%0 = call i8* @objc_autoreleaseReturnValue(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RetainBlock is not strictly forwarding. Do not touch it. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CHECK: define void @test_retainBlock(i8* %x) [[NUW]] {
; CHECK: call i8* @objc_retainBlock(i8* %x)
; CHECK: call void @use_pointer(i8* %0)
; CHECK: }
define void @test_retainBlock(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retainBlock(i8* %x) nounwind
call void @use_pointer(i8* %0)
ret void
}

View File

@@ -1,41 +0,0 @@
; RUN: opt -S -basicaa -objc-arc-aa -gvn < %s | FileCheck %s
@x = common global i8* null, align 8
declare i8* @objc_retain(i8*)
declare i32 @objc_sync_enter(i8*)
declare i32 @objc_sync_exit(i8*)
; GVN should be able to eliminate this redundant load, with ARC-specific
; alias analysis.
; CHECK: define i8* @test0(i32 %n)
; CHECK-NEXT: entry:
; CHECK-NEXT: %s = load i8*, i8** @x
; CHECK-NOT: load
; CHECK: ret i8* %s
; CHECK-NEXT: }
define i8* @test0(i32 %n) nounwind {
entry:
%s = load i8*, i8** @x
%0 = tail call i8* @objc_retain(i8* %s) nounwind
%t = load i8*, i8** @x
ret i8* %t
}
; GVN should not be able to eliminate this redundant load, with ARC-specific
; alias analysis.
; CHECK-LABEL: define i8* @test1(
; CHECK: load
; CHECK: load
; CHECK: ret i8* %t
; CHECK: }
define i8* @test1(i32 %n) nounwind {
entry:
%s = load i8*, i8** @x
%0 = call i32 @objc_sync_enter(i8* %s)
%t = load i8*, i8** @x
%1 = call i32 @objc_sync_exit(i8* %s)
ret i8* %t
}

View File

@@ -1,16 +0,0 @@
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
; This file makes sure that clang.arc.used is removed even if no other ARC
; interesting calls are in the module.
declare void @clang.arc.use(...) nounwind
; Kill calls to @clang.arc.use(...)
; CHECK-LABEL: define void @test0(
; CHECK-NOT: clang.arc.use
; CHECK: }
define void @test0(i8* %a, i8* %b) {
call void (...) @clang.arc.use(i8* %a, i8* %b) nounwind
ret void
}

View File

@@ -1,113 +0,0 @@
; RUN: opt -basicaa -objc-arc -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64"
declare i8* @objc_retain(i8*)
declare i8* @objc_retainAutorelease(i8*)
declare void @objc_release(i8*)
declare i8* @objc_autorelease(i8*)
declare void @clang.arc.use(...)
declare void @test0_helper(i8*, i8**)
; Ensure that we honor clang.arc.use as a use and don't miscompile
; the reduced test case from <rdar://13195034>.
;
; CHECK-LABEL: define void @test0(
; CHECK: @objc_retain(i8* %x)
; CHECK-NEXT: store i8* %y, i8** %temp0
; CHECK-NEXT: @objc_retain(i8* %y)
; CHECK-NEXT: call void @test0_helper
; CHECK-NEXT: [[VAL1:%.*]] = load i8*, i8** %temp0
; CHECK-NEXT: @objc_retain(i8* [[VAL1]])
; CHECK-NEXT: call void (...) @clang.arc.use(i8* %y)
; CHECK-NEXT: @objc_release(i8* %y)
; CHECK-NEXT: store i8* [[VAL1]], i8** %temp1
; CHECK-NEXT: call void @test0_helper
; CHECK-NEXT: [[VAL2:%.*]] = load i8*, i8** %temp1
; CHECK-NEXT: @objc_retain(i8* [[VAL2]])
; CHECK-NEXT: call void (...) @clang.arc.use(i8* [[VAL1]])
; CHECK-NEXT: @objc_release(i8* [[VAL1]])
; CHECK-NEXT: @objc_autorelease(i8* %x)
; CHECK-NEXT: store i8* %x, i8** %out
; CHECK-NEXT: @objc_retain(i8* %x)
; CHECK-NEXT: @objc_release(i8* [[VAL2]])
; CHECK-NEXT: @objc_release(i8* %x)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test0(i8** %out, i8* %x, i8* %y) {
entry:
%temp0 = alloca i8*, align 8
%temp1 = alloca i8*, align 8
%0 = call i8* @objc_retain(i8* %x) nounwind
%1 = call i8* @objc_retain(i8* %y) nounwind
store i8* %y, i8** %temp0
call void @test0_helper(i8* %x, i8** %temp0)
%val1 = load i8*, i8** %temp0
%2 = call i8* @objc_retain(i8* %val1) nounwind
call void (...) @clang.arc.use(i8* %y) nounwind
call void @objc_release(i8* %y) nounwind
store i8* %val1, i8** %temp1
call void @test0_helper(i8* %x, i8** %temp1)
%val2 = load i8*, i8** %temp1
%3 = call i8* @objc_retain(i8* %val2) nounwind
call void (...) @clang.arc.use(i8* %val1) nounwind
call void @objc_release(i8* %val1) nounwind
%4 = call i8* @objc_retain(i8* %x) nounwind
%5 = call i8* @objc_autorelease(i8* %x) nounwind
store i8* %x, i8** %out
call void @objc_release(i8* %val2) nounwind
call void @objc_release(i8* %x) nounwind
ret void
}
; CHECK-LABEL: define void @test0a(
; CHECK: @objc_retain(i8* %x)
; CHECK-NEXT: store i8* %y, i8** %temp0
; CHECK-NEXT: @objc_retain(i8* %y)
; CHECK-NEXT: call void @test0_helper
; CHECK-NEXT: [[VAL1:%.*]] = load i8*, i8** %temp0
; CHECK-NEXT: @objc_retain(i8* [[VAL1]])
; CHECK-NEXT: call void (...) @clang.arc.use(i8* %y)
; CHECK-NEXT: @objc_release(i8* %y)
; CHECK-NEXT: store i8* [[VAL1]], i8** %temp1
; CHECK-NEXT: call void @test0_helper
; CHECK-NEXT: [[VAL2:%.*]] = load i8*, i8** %temp1
; CHECK-NEXT: @objc_retain(i8* [[VAL2]])
; CHECK-NEXT: call void (...) @clang.arc.use(i8* [[VAL1]])
; CHECK-NEXT: @objc_release(i8* [[VAL1]])
; CHECK-NEXT: @objc_autorelease(i8* %x)
; CHECK-NEXT: @objc_release(i8* [[VAL2]])
; CHECK-NEXT: store i8* %x, i8** %out
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test0a(i8** %out, i8* %x, i8* %y) {
entry:
%temp0 = alloca i8*, align 8
%temp1 = alloca i8*, align 8
%0 = call i8* @objc_retain(i8* %x) nounwind
%1 = call i8* @objc_retain(i8* %y) nounwind
store i8* %y, i8** %temp0
call void @test0_helper(i8* %x, i8** %temp0)
%val1 = load i8*, i8** %temp0
%2 = call i8* @objc_retain(i8* %val1) nounwind
call void (...) @clang.arc.use(i8* %y) nounwind
call void @objc_release(i8* %y) nounwind, !clang.imprecise_release !0
store i8* %val1, i8** %temp1
call void @test0_helper(i8* %x, i8** %temp1)
%val2 = load i8*, i8** %temp1
%3 = call i8* @objc_retain(i8* %val2) nounwind
call void (...) @clang.arc.use(i8* %val1) nounwind
call void @objc_release(i8* %val1) nounwind, !clang.imprecise_release !0
%4 = call i8* @objc_retain(i8* %x) nounwind
%5 = call i8* @objc_autorelease(i8* %x) nounwind
store i8* %x, i8** %out
call void @objc_release(i8* %val2) nounwind, !clang.imprecise_release !0
call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
ret void
}
!0 = !{}

Some files were not shown because too many files have changed in this diff Show More