aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/ObjCARC
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2013-03-14 10:51:38 +0000
committerAlexander Kornienko <alexfh@google.com>2013-03-14 10:51:38 +0000
commit647735c781c5b37061ee03d6e9e6c7dda92218e2 (patch)
tree5a5e56606d41060263048b5a5586b3d2380898ba /test/Transforms/ObjCARC
parent6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (diff)
parentf635ef401786c84df32090251a8cf45981ecca33 (diff)
Updating branches/google/stable to r176857
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/stable@177040 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Transforms/ObjCARC')
-rw-r--r--test/Transforms/ObjCARC/apelim.ll6
-rw-r--r--test/Transforms/ObjCARC/basic.ll47
-rw-r--r--test/Transforms/ObjCARC/cfg-hazards.ll42
-rw-r--r--test/Transforms/ObjCARC/contract-marker.ll4
-rw-r--r--test/Transforms/ObjCARC/contract-storestrong.ll30
-rw-r--r--test/Transforms/ObjCARC/contract-testcases.ll5
-rw-r--r--test/Transforms/ObjCARC/contract.ll26
-rw-r--r--test/Transforms/ObjCARC/dont-infinite-loop-during-block-escape-analysis.ll87
-rw-r--r--test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll174
-rw-r--r--test/Transforms/ObjCARC/escape.ll7
-rw-r--r--test/Transforms/ObjCARC/gvn.ll2
-rw-r--r--test/Transforms/ObjCARC/invoke.ll16
-rw-r--r--test/Transforms/ObjCARC/move-and-form-retain-autorelease.ll6
-rw-r--r--test/Transforms/ObjCARC/nested.ll9
-rw-r--r--test/Transforms/ObjCARC/pr12270.ll2
-rw-r--r--test/Transforms/ObjCARC/retain-block-alloca.ll6
-rw-r--r--test/Transforms/ObjCARC/retain-block-side-effects.ll5
-rw-r--r--test/Transforms/ObjCARC/retain-block.ll26
-rw-r--r--test/Transforms/ObjCARC/retain-not-declared.ll4
-rw-r--r--test/Transforms/ObjCARC/rle-s2l.ll7
-rw-r--r--test/Transforms/ObjCARC/rv.ll26
-rw-r--r--test/Transforms/ObjCARC/split-backedge.ll14
-rw-r--r--test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll84
-rw-r--r--test/Transforms/ObjCARC/weak-copies.ll6
24 files changed, 516 insertions, 125 deletions
diff --git a/test/Transforms/ObjCARC/apelim.ll b/test/Transforms/ObjCARC/apelim.ll
index 8c7b5b1e65..4541b3f2fd 100644
--- a/test/Transforms/ObjCARC/apelim.ll
+++ b/test/Transforms/ObjCARC/apelim.ll
@@ -38,8 +38,8 @@ entry:
}
; CHECK: define internal void @_GLOBAL__I_y()
-; CHECK: %0 = call i8* @objc_autoreleasePoolPush() nounwind
-; CHECK: call void @objc_autoreleasePoolPop(i8* %0) nounwind
+; 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:
@@ -51,3 +51,5 @@ entry:
declare i8* @objc_autoreleasePoolPush()
declare void @objc_autoreleasePoolPop(i8*)
+
+; CHECK: attributes #0 = { nounwind }
diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll
index 7b64b1be7c..4c24ebf865 100644
--- a/test/Transforms/ObjCARC/basic.ll
+++ b/test/Transforms/ObjCARC/basic.ll
@@ -92,10 +92,10 @@ alt_return:
; CHECK: define void @test1b(
; CHECK: entry:
-; CHECK: tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW:#[0-9]+]]
; CHECK-NOT: @objc_
; CHECK: if.end5:
-; CHECK: tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
+; CHECK: tail call void @objc_release(i8* %x) [[NUW]], !clang.imprecise_release !0
; CHECK-NOT: @objc_
; CHECK: }
define void @test1b(i8* %x, i1 %p, i1 %q) {
@@ -404,8 +404,8 @@ entry:
; a stack argument.
; CHECK: define void @test11(
-; CHECK: tail call i8* @objc_retain(i8* %x) nounwind
-; CHECK: tail call i8* @objc_autorelease(i8* %0) nounwind
+; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]]
+; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]]
; CHECK: }
define void @test11(i8* %x) nounwind {
entry:
@@ -431,8 +431,8 @@ entry:
; Same as test11 but the value is returned. Do an RV optimization.
; CHECK: define i8* @test11b(
-; CHECK: tail call i8* @objc_retain(i8* %x) nounwind
-; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind
+; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]]
+; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %0) [[NUW]]
; CHECK: }
define i8* @test11b(i8* %x) nounwind {
entry:
@@ -462,10 +462,10 @@ entry:
; Trivial retain,autorelease pair. Don't delete!
; CHECK: define void @test13(
-; CHECK: tail call i8* @objc_retain(i8* %x) nounwind
-; CHECK: tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]]
+; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]]
; CHECK: @use_pointer(i8* %x)
-; CHECK: tail call i8* @objc_autorelease(i8* %x) nounwind
+; CHECK: call i8* @objc_autorelease(i8* %x) [[NUW]]
; CHECK: }
define void @test13(i8* %x, i64 %n) {
entry:
@@ -716,7 +716,7 @@ entry:
; Bitcast insertion
; CHECK: define void @test20(
-; CHECK: %tmp1 = tail call i8* @objc_retain(i8* %tmp) nounwind
+; CHECK: %tmp1 = tail call i8* @objc_retain(i8* %tmp) [[NUW]]
; CHECK-NEXT: invoke
define void @test20(double* %self) {
if.then12:
@@ -980,7 +980,7 @@ done:
; CHECK: call i8* @objc_retain(
; CHECK: call void @callee()
; CHECK: store
-; CHECK: call void @objc_release(i8* %p) nounwind, !clang.imprecise_release
+; CHECK: call void @objc_release(i8* %p) [[NUW]], !clang.imprecise_release
; CHECK: done:
; CHECK-NOT: @objc_
; CHECK: }
@@ -1450,9 +1450,9 @@ define void @test45(i8** %pp, i8** %qq) {
; Don't delete retain and autorelease here.
; CHECK: define void @test46(
-; CHECK: tail call i8* @objc_retain(i8* %p) nounwind
+; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK: true:
-; CHECK: tail call i8* @objc_autorelease(i8* %p) nounwind
+; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]]
define void @test46(i8* %p, i1 %a) {
entry:
call i8* @objc_retain(i8* %p)
@@ -1565,7 +1565,7 @@ define void @test53(void ()** %zz, i8** %pp) {
; CHECK: define void @test54(
; CHECK: call i8* @returner()
-; CHECK-NEXT: call void @objc_release(i8* %t) nounwind, !clang.imprecise_release !0
+; CHECK-NEXT: call void @objc_release(i8* %t) [[NUW]], !clang.imprecise_release !0
; CHECK-NEXT: ret void
define void @test54() {
%t = call i8* @returner()
@@ -1595,10 +1595,10 @@ entry:
; CHECK: define void @test56(
; CHECK-NOT: @objc
; CHECK: if.then:
-; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]]
; CHECK-NEXT: tail call void @use_pointer(i8* %x)
; CHECK-NEXT: tail call void @use_pointer(i8* %x)
-; CHECK-NEXT: tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
+; CHECK-NEXT: tail call void @objc_release(i8* %x) [[NUW]], !clang.imprecise_release !0
; CHECK-NEXT: br label %if.end
; CHECK-NOT: @objc
; CHECK: }
@@ -1630,10 +1630,10 @@ if.end: ; preds = %entry, %if.then
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @use_pointer(i8* %x)
; CHECK-NEXT: call void @use_pointer(i8* %x)
-; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]]
; CHECK-NEXT: call void @use_pointer(i8* %x)
; CHECK-NEXT: call void @use_pointer(i8* %x)
-; CHECK-NEXT: call void @objc_release(i8* %x) nounwind
+; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test57(i8* %x) nounwind {
@@ -1673,10 +1673,10 @@ entry:
; CHECK: define void @test59(
; CHECK-NEXT: entry:
-; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]]
; CHECK-NEXT: call void @use_pointer(i8* %x)
; CHECK-NEXT: call void @use_pointer(i8* %x)
-; CHECK-NEXT: call void @objc_release(i8* %x) nounwind
+; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test59(i8* %x) nounwind {
@@ -1875,8 +1875,8 @@ return: ; preds = %if.then, %entry
; rdar://11931823
; CHECK: define void @test66(
-; CHECK: %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind
-; CHECK: tail call void @objc_release(i8* %cond) nounwind
+; CHECK: %tmp7 = tail call i8* @objc_retain(i8* %cond) [[NUW]]
+; CHECK: tail call void @objc_release(i8* %cond) [[NUW]]
; CHECK: }
define void @test66(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) {
entry:
@@ -2224,3 +2224,6 @@ end: ; preds = %if.end125, %if.end1
!0 = metadata !{}
declare i32 @__gxx_personality_v0(...)
+
+; CHECK: attributes #0 = { nounwind readnone }
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/ObjCARC/cfg-hazards.ll b/test/Transforms/ObjCARC/cfg-hazards.ll
index 15194237c4..899298b596 100644
--- a/test/Transforms/ObjCARC/cfg-hazards.ll
+++ b/test/Transforms/ObjCARC/cfg-hazards.ll
@@ -86,9 +86,9 @@ for.end: ; preds = %for.body
; Delete nested retain+release pairs around loops.
-; CHECK: define void @test3(i8* %a) nounwind {
+; CHECK: define void @test3(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW:#[0-9]+]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
@@ -112,9 +112,9 @@ exit:
ret void
}
-; CHECK: define void @test4(i8* %a) nounwind {
+; CHECK: define void @test4(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
@@ -142,9 +142,9 @@ exit:
ret void
}
-; CHECK: define void @test5(i8* %a) nounwind {
+; CHECK: define void @test5(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: call void @callee()
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
@@ -176,9 +176,9 @@ exit:
ret void
}
-; CHECK: define void @test6(i8* %a) nounwind {
+; CHECK: define void @test6(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
@@ -209,9 +209,9 @@ exit:
ret void
}
-; CHECK: define void @test7(i8* %a) nounwind {
+; CHECK: define void @test7(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: call void @callee()
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
@@ -242,9 +242,9 @@ exit:
ret void
}
-; CHECK: define void @test8(i8* %a) nounwind {
+; CHECK: define void @test8(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) [[NUW]]
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
; CHECK: exit:
@@ -274,7 +274,7 @@ exit:
ret void
}
-; CHECK: define void @test9(i8* %a) nounwind {
+; CHECK: define void @test9(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
@@ -303,7 +303,7 @@ exit:
ret void
}
-; CHECK: define void @test10(i8* %a) nounwind {
+; CHECK: define void @test10(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
@@ -332,7 +332,7 @@ exit:
ret void
}
-; CHECK: define void @test11(i8* %a) nounwind {
+; CHECK: define void @test11(i8* %a) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %loop
; CHECK-NOT: @objc_
@@ -362,15 +362,15 @@ exit:
; Don't delete anything if they're not balanced.
-; CHECK: define void @test12(i8* %a) nounwind {
+; CHECK: define void @test12(i8* %a) #0 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: %outer = tail call i8* @objc_retain(i8* %a) nounwind
-; CHECK-NEXT: %inner = tail call i8* @objc_retain(i8* %a) nounwind
+; 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) nounwind
-; CHECK-NEXT: call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+; 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 {
@@ -394,4 +394,6 @@ exit:
ret void
}
+; CHECK: attributes [[NUW]] = { nounwind }
+
!0 = metadata !{}
diff --git a/test/Transforms/ObjCARC/contract-marker.ll b/test/Transforms/ObjCARC/contract-marker.ll
index 01d978a0e2..01fd1e7143 100644
--- a/test/Transforms/ObjCARC/contract-marker.ll
+++ b/test/Transforms/ObjCARC/contract-marker.ll
@@ -3,7 +3,7 @@
; 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 objc_retainAutoreleaseReturnValue", ""()
-; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tcall) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
define void @foo() {
entry:
@@ -21,3 +21,5 @@ declare void @bar(i8*)
!clang.arc.retainAutoreleasedReturnValueMarker = !{!0}
!0 = metadata !{metadata !"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"}
+
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/ObjCARC/contract-storestrong.ll b/test/Transforms/ObjCARC/contract-storestrong.ll
index 2922f816d5..6999237300 100644
--- a/test/Transforms/ObjCARC/contract-storestrong.ll
+++ b/test/Transforms/ObjCARC/contract-storestrong.ll
@@ -10,7 +10,7 @@ declare void @use_pointer(i8*)
; CHECK: define void @test0(
; CHECK: entry:
-; CHECK-NEXT: tail call void @objc_storeStrong(i8** @x, i8* %p) nounwind
+; CHECK-NEXT: tail call void @objc_storeStrong(i8** @x, i8* %p) [[NUW:#[0-9]+]]
; CHECK-NEXT: ret void
define void @test0(i8* %p) {
entry:
@@ -25,10 +25,10 @@ entry:
; CHECK: define void @test1(i8* %p) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK-NEXT: %tmp = load volatile i8** @x, align 8
; CHECK-NEXT: store i8* %0, i8** @x, align 8
-; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
+; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test1(i8* %p) {
@@ -44,10 +44,10 @@ entry:
; CHECK: define void @test2(i8* %p) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK-NEXT: %tmp = load i8** @x, align 8
; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8
-; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
+; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test2(i8* %p) {
@@ -64,11 +64,11 @@ entry:
; CHECK: define void @test3(i8* %newValue) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
+; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) [[NUW]]
; CHECK-NEXT: %x1 = load 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) nounwind, !clang.imprecise_release !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) {
@@ -85,11 +85,11 @@ entry:
; CHECK: define i1 @test4(i8* %newValue, i8* %foo) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
+; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) [[NUW]]
; CHECK-NEXT: %x1 = load 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) nounwind, !clang.imprecise_release !0
+; 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) {
@@ -106,7 +106,7 @@ entry:
; CHECK: define i1 @test5(i8* %newValue, i8* %foo) {
; CHECK: %t = icmp eq i8* %x1, %foo
-; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) nounwind
+; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) [[NUW]]
define i1 @test5(i8* %newValue, i8* %foo) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
@@ -121,7 +121,7 @@ entry:
; CHECK: define i1 @test6(i8* %newValue, i8* %foo) {
; CHECK: %t = icmp eq i8* %x1, %foo
-; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) nounwind
+; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) [[NUW]]
define i1 @test6(i8* %newValue, i8* %foo) {
entry:
%x0 = tail call i8* @objc_retain(i8* %newValue) nounwind
@@ -136,9 +136,9 @@ entry:
; CHECK: define void @test7(
; CHECK-NEXT: entry:
-; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK-NEXT: %tmp = load i8** @x, align 8
-; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
+; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test7(i8* %p) {
@@ -155,7 +155,7 @@ entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: %tmp = load i8** @x, align 8
; CHECK-NEXT: store i8* %p, i8** @x, align 8
-; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
+; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]]
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test8(i8* %p) {
@@ -167,3 +167,5 @@ entry:
}
!0 = metadata !{}
+
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/ObjCARC/contract-testcases.ll b/test/Transforms/ObjCARC/contract-testcases.ll
index 1510ed00e6..85b03be275 100644
--- a/test/Transforms/ObjCARC/contract-testcases.ll
+++ b/test/Transforms/ObjCARC/contract-testcases.ll
@@ -69,7 +69,7 @@ bb7: ; preds = %bb6, %bb6, %bb5
; CHECK: define void @_Z6doTestP8NSString() {
; 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) nounwind
+; CHECK-NEXT: %tmp = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) [[NUW:#[0-9]+]]
define void @_Z6doTestP8NSString() {
entry:
%call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* ()*)()
@@ -88,3 +88,6 @@ lpad: ; preds = %entry
!clang.arc.retainAutoreleasedReturnValueMarker = !{!0}
!0 = metadata !{metadata !"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"}
+
+; CHECK: attributes #0 = { optsize }
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/ObjCARC/contract.ll b/test/Transforms/ObjCARC/contract.ll
index c48f8a534f..b6fba59603 100644
--- a/test/Transforms/ObjCARC/contract.ll
+++ b/test/Transforms/ObjCARC/contract.ll
@@ -34,12 +34,12 @@ entry:
; Merge objc_retain and objc_autorelease into objc_retainAutorelease.
; CHECK: define void @test2(
-; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) nounwind
+; 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
- tail call i8* @objc_autorelease(i8* %0) nounwind
+ call i8* @objc_autorelease(i8* %0) nounwind
call void @use_pointer(i8* %x)
ret void
}
@@ -47,7 +47,7 @@ entry:
; Same as test2 but the value is returned. Do an RV optimization.
; CHECK: define i8* @test2b(
-; CHECK: tail call i8* @objc_retainAutoreleaseReturnValue(i8* %x) nounwind
+; CHECK: tail call i8* @objc_retainAutoreleaseReturnValue(i8* %x) [[NUW]]
; CHECK: }
define i8* @test2b(i8* %x) nounwind {
entry:
@@ -59,14 +59,14 @@ entry:
; Merge a retain,autorelease pair around a call.
; CHECK: define void @test3(
-; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) nounwind
+; 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)
- tail call i8* @objc_autorelease(i8* %x) nounwind
+ call i8* @objc_autorelease(i8* %x) nounwind
ret void
}
@@ -75,7 +75,7 @@ entry:
; CHECK: define void @test4(
; CHECK-NEXT: entry:
-; CHECK-NEXT: @objc_retainAutorelease(i8* %x) nounwind
+; CHECK-NEXT: @objc_retainAutorelease(i8* %x) [[NUW]]
; CHECK-NEXT: @use_pointer
; CHECK-NEXT: @objc_release
; CHECK-NEXT: ret void
@@ -84,7 +84,7 @@ define void @test4(i8* %x, i64 %n) {
entry:
tail call i8* @objc_retain(i8* %x) nounwind
call void @use_pointer(i8* %x)
- tail call i8* @objc_autorelease(i8* %x) nounwind
+ call i8* @objc_autorelease(i8* %x) nounwind
tail call void @objc_release(i8* %x) nounwind
ret void
}
@@ -92,9 +92,9 @@ entry:
; Don't merge retain and autorelease if they're not control-equivalent.
; CHECK: define void @test5(
-; CHECK: tail call i8* @objc_retain(i8* %p) nounwind
+; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]]
; CHECK: true:
-; CHECK: tail call i8* @objc_autorelease(i8* %0) nounwind
+; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]]
; CHECK: }
define void @test5(i8* %p, i1 %a) {
entry:
@@ -102,7 +102,7 @@ entry:
br i1 %a, label %true, label %false
true:
- tail call i8* @objc_autorelease(i8* %p) nounwind
+ call i8* @objc_autorelease(i8* %p) nounwind
call void @use_pointer(i8* %p)
ret void
@@ -119,8 +119,8 @@ false:
; Those entrypoints don't exist yet though.
; CHECK: define i8* @test6(
-; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %p) nounwind
-; CHECK: %t = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
+; 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()
@@ -161,3 +161,5 @@ return: ; preds = %if.then, %entry
%retval = phi i8* [ %c, %if.then ], [ null, %entry ]
ret i8* %retval
}
+
+; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/ObjCARC/dont-infinite-loop-during-block-escape-analysis.ll b/test/Transforms/ObjCARC/dont-infinite-loop-during-block-escape-analysis.ll
new file mode 100644
index 0000000000..bdee2be94f
--- /dev/null
+++ b/test/Transforms/ObjCARC/dont-infinite-loop-during-block-escape-analysis.ll
@@ -0,0 +1,87 @@
+; RUN: opt -S -objc-arc < %s
+; bugzilla://14551
+; rdar://12851911
+
+; Make sure that we do not hang clang during escape analysis.
+
+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-darwin"
+
+%struct.__block_descriptor = type { i64, i64 }
+%struct.__block_byref_foo = type { i8*, %struct.__block_byref_foo*, i32, i32, i32 }
+
+@_NSConcreteGlobalBlock = external global i8*
+@.str = private unnamed_addr constant [6 x i8] c"v8@?0\00", align 1
+@__block_descriptor_tmp = internal constant { i64, i64, i8*, i8* } { i64 0, i64 32, i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i8* null }
+@__block_literal_global = internal constant { i8**, i32, i32, i8*, %struct.__block_descriptor* } { i8** @_NSConcreteGlobalBlock, i32 1342177280, i32 0, i8* bitcast (void (i8*)* @__hang_clang_block_invoke to i8*), %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*) }, align 8
+
+define void @hang_clang() uwtable optsize ssp {
+entry:
+ %foo = alloca %struct.__block_byref_foo, align 8
+ %byref.isa = getelementptr inbounds %struct.__block_byref_foo* %foo, i64 0, i32 0
+ store i8* null, i8** %byref.isa, align 8
+ %byref.forwarding = getelementptr inbounds %struct.__block_byref_foo* %foo, i64 0, i32 1
+ store %struct.__block_byref_foo* %foo, %struct.__block_byref_foo** %byref.forwarding, align 8
+ %byref.flags = getelementptr inbounds %struct.__block_byref_foo* %foo, i64 0, i32 2
+ store i32 536870912, i32* %byref.flags, align 8
+ %byref.size = getelementptr inbounds %struct.__block_byref_foo* %foo, i64 0, i32 3
+ store i32 32, i32* %byref.size, align 4
+ %foo1 = getelementptr inbounds %struct.__block_byref_foo* %foo, i64 0, i32 4
+ store i32 0, i32* %foo1, align 8, !tbaa !4
+ br label %for.body
+
+for.body: ; preds = %for.inc.for.body_crit_edge, %entry
+ %0 = phi i1 [ true, %entry ], [ %phitmp, %for.inc.for.body_crit_edge ]
+ %i.06 = phi i32 [ 1, %entry ], [ %phitmp8, %for.inc.for.body_crit_edge ]
+ %block.05 = phi void (...)* [ null, %entry ], [ %block.1, %for.inc.for.body_crit_edge ]
+ br i1 %0, label %for.inc, label %if.then
+
+if.then: ; preds = %for.body
+ %1 = call i8* @objc_retainBlock(i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor* }* @__block_literal_global to i8*)) nounwind, !clang.arc.copy_on_escape !7
+ %2 = bitcast i8* %1 to void (...)*
+ %3 = bitcast void (...)* %block.05 to i8*
+ call void @objc_release(i8* %3) nounwind, !clang.imprecise_release !7
+ br label %for.inc
+
+for.inc: ; preds = %for.body, %if.then
+ %block.1 = phi void (...)* [ %2, %if.then ], [ %block.05, %for.body ]
+ %exitcond = icmp eq i32 %i.06, 10
+ br i1 %exitcond, label %for.end, label %for.inc.for.body_crit_edge
+
+for.inc.for.body_crit_edge: ; preds = %for.inc
+ %.pre = load %struct.__block_byref_foo** %byref.forwarding, align 8
+ %foo2.phi.trans.insert = getelementptr inbounds %struct.__block_byref_foo* %.pre, i64 0, i32 4
+ %.pre7 = load i32* %foo2.phi.trans.insert, align 4, !tbaa !4
+ %phitmp = icmp eq i32 %.pre7, 0
+ %phitmp8 = add i32 %i.06, 1
+ br label %for.body
+
+for.end: ; preds = %for.inc
+ %4 = bitcast %struct.__block_byref_foo* %foo to i8*
+ call void @_Block_object_dispose(i8* %4, i32 8)
+ %5 = bitcast void (...)* %block.1 to i8*
+ call void @objc_release(i8* %5) nounwind, !clang.imprecise_release !7
+ ret void
+}
+
+define internal void @__hang_clang_block_invoke(i8* nocapture %.block_descriptor) nounwind uwtable readnone optsize ssp {
+entry:
+ ret void
+}
+
+declare i8* @objc_retainBlock(i8*)
+
+declare void @objc_release(i8*) nonlazybind
+
+declare void @_Block_object_dispose(i8*, i32)
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = metadata !{i32 1, metadata !"Objective-C Version", i32 2}
+!1 = metadata !{i32 1, metadata !"Objective-C Image Info Version", i32 0}
+!2 = metadata !{i32 1, metadata !"Objective-C Image Info Section", metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
+!3 = metadata !{i32 4, metadata !"Objective-C Garbage Collection", i32 0}
+!4 = metadata !{metadata !"int", metadata !5}
+!5 = metadata !{metadata !"omnipotent char", metadata !6}
+!6 = metadata !{metadata !"Simple C/C++ TBAA"}
+!7 = metadata !{}
diff --git a/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll b/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll
new file mode 100644
index 0000000000..05257d1d5c
--- /dev/null
+++ b/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll
@@ -0,0 +1,174 @@
+; 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]* @"\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 = linker_private unnamed_addr constant [11 x i8] c"Failed: %@\00", align 1
+@_unnamed_cfstring_ = private constant %struct.NSConstantString { i32* getelementptr inbounds ([0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([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 = linker_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]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([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]* @"\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 (%s