131 lines · plain
1; RUN: opt -passes=objc-arc -S < %s | FileCheck %s2 3target datalayout = "e-p:64:64:64"4 5declare ptr @llvm.objc.retain(ptr)6declare ptr @llvm.objc.retainAutorelease(ptr)7declare void @llvm.objc.release(ptr)8declare ptr @llvm.objc.autorelease(ptr)9 10declare void @llvm.objc.clang.arc.use(...)11declare void @llvm.objc.clang.arc.noop.use(...)12 13declare void @test0_helper(ptr, ptr)14declare void @can_release(ptr)15 16; Ensure that we honor clang.arc.use as a use and don't miscompile17; the reduced test case from <rdar://13195034>.18;19; CHECK-LABEL: define void @test0(20; CHECK: @llvm.objc.retain(ptr %x)21; CHECK-NEXT: store ptr %y, ptr %temp022; CHECK-NEXT: @llvm.objc.retain(ptr %y)23; CHECK-NEXT: call void @test0_helper24; CHECK-NEXT: [[VAL1:%.*]] = load ptr, ptr %temp025; CHECK-NEXT: @llvm.objc.retain(ptr [[VAL1]])26; CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr %y)27; CHECK-NEXT: @llvm.objc.release(ptr %y)28; CHECK-NEXT: store ptr [[VAL1]], ptr %temp129; CHECK-NEXT: call void @test0_helper30; CHECK-NEXT: [[VAL2:%.*]] = load ptr, ptr %temp131; CHECK-NEXT: @llvm.objc.retain(ptr [[VAL2]])32; CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]])33; CHECK-NEXT: @llvm.objc.release(ptr [[VAL1]])34; CHECK-NEXT: @llvm.objc.autorelease(ptr %x)35; CHECK-NEXT: store ptr %x, ptr %out36; CHECK-NEXT: @llvm.objc.retain(ptr %x)37; CHECK-NEXT: @llvm.objc.release(ptr [[VAL2]])38; CHECK-NEXT: @llvm.objc.release(ptr %x)39; CHECK-NEXT: ret void40; CHECK-NEXT: }41define void @test0(ptr %out, ptr %x, ptr %y) {42entry:43 %temp0 = alloca ptr, align 844 %temp1 = alloca ptr, align 845 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind46 %1 = call ptr @llvm.objc.retain(ptr %y) nounwind47 store ptr %y, ptr %temp048 call void @test0_helper(ptr %x, ptr %temp0)49 %val1 = load ptr, ptr %temp050 %2 = call ptr @llvm.objc.retain(ptr %val1) nounwind51 call void (...) @llvm.objc.clang.arc.use(ptr %y) nounwind52 call void @llvm.objc.release(ptr %y) nounwind53 store ptr %val1, ptr %temp154 call void @test0_helper(ptr %x, ptr %temp1)55 %val2 = load ptr, ptr %temp156 %3 = call ptr @llvm.objc.retain(ptr %val2) nounwind57 call void (...) @llvm.objc.clang.arc.use(ptr %val1) nounwind58 call void @llvm.objc.release(ptr %val1) nounwind59 %4 = call ptr @llvm.objc.retain(ptr %x) nounwind60 %5 = call ptr @llvm.objc.autorelease(ptr %x) nounwind61 store ptr %x, ptr %out62 call void @llvm.objc.release(ptr %val2) nounwind63 call void @llvm.objc.release(ptr %x) nounwind64 ret void65}66 67; CHECK-LABEL: define void @test0a(68; CHECK: @llvm.objc.retain(ptr %x)69; CHECK-NEXT: store ptr %y, ptr %temp070; CHECK-NEXT: @llvm.objc.retain(ptr %y)71; CHECK-NEXT: call void @test0_helper72; CHECK-NEXT: [[VAL1:%.*]] = load ptr, ptr %temp073; CHECK-NEXT: @llvm.objc.retain(ptr [[VAL1]])74; CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr %y)75; CHECK-NEXT: @llvm.objc.release(ptr %y)76; CHECK-NEXT: store ptr [[VAL1]], ptr %temp177; CHECK-NEXT: call void @test0_helper78; CHECK-NEXT: [[VAL2:%.*]] = load ptr, ptr %temp179; CHECK-NEXT: @llvm.objc.retain(ptr [[VAL2]])80; CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]])81; CHECK-NEXT: @llvm.objc.release(ptr [[VAL1]])82; CHECK-NEXT: @llvm.objc.autorelease(ptr %x)83; CHECK-NEXT: @llvm.objc.release(ptr [[VAL2]])84; CHECK-NEXT: store ptr %x, ptr %out85; CHECK-NEXT: ret void86; CHECK-NEXT: }87define void @test0a(ptr %out, ptr %x, ptr %y) {88entry:89 %temp0 = alloca ptr, align 890 %temp1 = alloca ptr, align 891 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind92 %1 = call ptr @llvm.objc.retain(ptr %y) nounwind93 store ptr %y, ptr %temp094 call void @test0_helper(ptr %x, ptr %temp0)95 %val1 = load ptr, ptr %temp096 %2 = call ptr @llvm.objc.retain(ptr %val1) nounwind97 call void (...) @llvm.objc.clang.arc.use(ptr %y) nounwind98 call void @llvm.objc.release(ptr %y) nounwind, !clang.imprecise_release !099 store ptr %val1, ptr %temp1100 call void @test0_helper(ptr %x, ptr %temp1)101 %val2 = load ptr, ptr %temp1102 %3 = call ptr @llvm.objc.retain(ptr %val2) nounwind103 call void (...) @llvm.objc.clang.arc.use(ptr %val1) nounwind104 call void @llvm.objc.release(ptr %val1) nounwind, !clang.imprecise_release !0105 %4 = call ptr @llvm.objc.retain(ptr %x) nounwind106 %5 = call ptr @llvm.objc.autorelease(ptr %x) nounwind107 store ptr %x, ptr %out108 call void @llvm.objc.release(ptr %val2) nounwind, !clang.imprecise_release !0109 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0110 ret void111}112 113; ARC optimizer should be able to safely remove the retain/release pair as the114; call to @llvm.objc.clang.arc.noop.use is a no-op.115 116; CHECK-LABEL: define void @test_arc_noop_use(117; CHECK-NEXT: call void @can_release(ptr %x)118; CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(119; CHECK-NEXT: ret void120 121define void @test_arc_noop_use(ptr %out, ptr %x) {122 call ptr @llvm.objc.retain(ptr %x)123 call void @can_release(ptr %x)124 call void (...) @llvm.objc.clang.arc.noop.use(ptr %x)125 call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0126 ret void127}128 129!0 = !{}130 131