17676817eSArthur Eubanks; RUN: opt -passes=objc-arc -S < %s | FileCheck %s 275fbb171SAkira Hatanaka 375fbb171SAkira Hatanakadeclare void @alterRefCount() 4*01e4f41bSMatt Arsenaultdeclare void @use(ptr) 5*01e4f41bSMatt Arsenaultdeclare void @readOnlyFunc(ptr, ptr) 675fbb171SAkira Hatanaka 7*01e4f41bSMatt Arsenault@g0 = global ptr null, align 8 832dc79c5SAkira Hatanaka 975fbb171SAkira Hatanaka; Check that ARC optimizer doesn't reverse the order of the retain call and the 1075fbb171SAkira Hatanaka; release call when there are debug instructions. 1175fbb171SAkira Hatanaka 12*01e4f41bSMatt Arsenault; CHECK: call ptr @llvm.objc.retain(ptr %x) 13*01e4f41bSMatt Arsenault; CHECK: call void @llvm.objc.release(ptr %x) 1475fbb171SAkira Hatanaka 15*01e4f41bSMatt Arsenaultdefine i32 @test(ptr %x, ptr %y, i8 %z, i32 %i) { 1675fbb171SAkira Hatanaka %i.addr = alloca i32, align 4 17*01e4f41bSMatt Arsenault store i32 %i, ptr %i.addr, align 4 18*01e4f41bSMatt Arsenault %v1 = tail call ptr @llvm.objc.retain(ptr %x) 19*01e4f41bSMatt Arsenault store i8 %z, ptr %x 20*01e4f41bSMatt Arsenault call void @llvm.dbg.declare(metadata ptr %i.addr, metadata !9, metadata !DIExpression()), !dbg !10 2175fbb171SAkira Hatanaka call void @alterRefCount() 22*01e4f41bSMatt Arsenault tail call void @llvm.objc.release(ptr %x) 2375fbb171SAkira Hatanaka ret i32 %i 2475fbb171SAkira Hatanaka} 2575fbb171SAkira Hatanaka 2632dc79c5SAkira Hatanaka; ARC optimizer shouldn't move the release call, which is a precise release call 2732dc79c5SAkira Hatanaka; past the call to @alterRefCount. 2832dc79c5SAkira Hatanaka 2932dc79c5SAkira Hatanaka; CHECK-LABEL: define void @test2( 3032dc79c5SAkira Hatanaka; CHECK: call void @alterRefCount( 3132dc79c5SAkira Hatanaka; CHECK: call void @llvm.objc.release( 3232dc79c5SAkira Hatanaka 3332dc79c5SAkira Hatanakadefine void @test2() { 34*01e4f41bSMatt Arsenault %v0 = load ptr, ptr @g0, align 8 35*01e4f41bSMatt Arsenault %v1 = tail call ptr @llvm.objc.retain(ptr %v0) 36*01e4f41bSMatt Arsenault tail call void @use(ptr %v0) 3732dc79c5SAkira Hatanaka tail call void @alterRefCount() 38*01e4f41bSMatt Arsenault tail call void @llvm.objc.release(ptr %v0) 3932dc79c5SAkira Hatanaka ret void 4032dc79c5SAkira Hatanaka} 4132dc79c5SAkira Hatanaka 4228fe9afdSAkira Hatanaka; Check that code motion is disabled in @test3 and @test4. 4328fe9afdSAkira Hatanaka; Previously, ARC optimizer would move the release past the retain. 4428fe9afdSAkira Hatanaka 4528fe9afdSAkira Hatanaka; if.then: 46*01e4f41bSMatt Arsenault; call void @readOnlyFunc(ptr %obj, ptr null) 47*01e4f41bSMatt Arsenault; call void @llvm.objc.release(ptr %obj) #1, !clang.imprecise_release !2 4828fe9afdSAkira Hatanaka; %1 = add i32 1, 2 49*01e4f41bSMatt Arsenault; %2 = tail call ptr @llvm.objc.retain(ptr %obj) 5028fe9afdSAkira Hatanaka; 5128fe9afdSAkira Hatanaka; Ideally, the retain/release pairs in BB if.then should be removed. 5276dd98ecSAkira Hatanaka 53*01e4f41bSMatt Arsenaultdefine void @test3(ptr %obj, i1 %cond) { 5476dd98ecSAkira Hatanaka; CHECK-LABEL: @test3( 55*01e4f41bSMatt Arsenault; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ:%.*]]) 5676dd98ecSAkira Hatanaka; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 5776dd98ecSAkira Hatanaka; CHECK: if.then: 58*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @readOnlyFunc(ptr [[OBJ]], ptr null) 5976dd98ecSAkira Hatanaka; CHECK-NEXT: [[TMP1:%.*]] = add i32 1, 2 6076dd98ecSAkira Hatanaka; CHECK-NEXT: call void @alterRefCount() 6176dd98ecSAkira Hatanaka; CHECK-NEXT: br label [[JOIN:%.*]] 6276dd98ecSAkira Hatanaka; CHECK: if.else: 6376dd98ecSAkira Hatanaka; CHECK-NEXT: call void @alterRefCount() 64*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @use(ptr [[OBJ]]) 6576dd98ecSAkira Hatanaka; CHECK-NEXT: br label [[JOIN]] 6676dd98ecSAkira Hatanaka; CHECK: join: 67*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @llvm.objc.release(ptr [[OBJ]]) {{.*}}, !clang.imprecise_release !2 6876dd98ecSAkira Hatanaka; CHECK-NEXT: ret void 6976dd98ecSAkira Hatanaka; 70*01e4f41bSMatt Arsenault %v0 = call ptr @llvm.objc.retain(ptr %obj) 7176dd98ecSAkira Hatanaka br i1 %cond, label %if.then, label %if.else 7276dd98ecSAkira Hatanaka 7376dd98ecSAkira Hatanakaif.then: 74*01e4f41bSMatt Arsenault call void @readOnlyFunc(ptr %obj, ptr null) #0 7576dd98ecSAkira Hatanaka add i32 1, 2 7676dd98ecSAkira Hatanaka call void @alterRefCount() 7776dd98ecSAkira Hatanaka br label %join 7876dd98ecSAkira Hatanaka 7976dd98ecSAkira Hatanakaif.else: 8076dd98ecSAkira Hatanaka call void @alterRefCount() 81*01e4f41bSMatt Arsenault call void @use(ptr %obj) 8276dd98ecSAkira Hatanaka br label %join 8376dd98ecSAkira Hatanaka 8476dd98ecSAkira Hatanakajoin: 85*01e4f41bSMatt Arsenault call void @llvm.objc.release(ptr %obj), !clang.imprecise_release !9 8676dd98ecSAkira Hatanaka ret void 8776dd98ecSAkira Hatanaka} 8876dd98ecSAkira Hatanaka 89*01e4f41bSMatt Arsenaultdefine void @test4(ptr %obj0, ptr %obj1, i1 %cond) { 9076dd98ecSAkira Hatanaka; CHECK-LABEL: @test4( 91*01e4f41bSMatt Arsenault; CHECK-NEXT: [[TMP3:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ0:%.*]]) 92*01e4f41bSMatt Arsenault; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ1:%.*]]) 9376dd98ecSAkira Hatanaka; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 9476dd98ecSAkira Hatanaka; CHECK: if.then: 95*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @readOnlyFunc(ptr [[OBJ0]], ptr [[OBJ1]]) 9676dd98ecSAkira Hatanaka; CHECK-NEXT: [[TMP1:%.*]] = add i32 1, 2 9776dd98ecSAkira Hatanaka; CHECK-NEXT: call void @alterRefCount() 9876dd98ecSAkira Hatanaka; CHECK-NEXT: br label [[JOIN:%.*]] 9976dd98ecSAkira Hatanaka; CHECK: if.else: 10076dd98ecSAkira Hatanaka; CHECK-NEXT: call void @alterRefCount() 101*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @use(ptr [[OBJ0]]) 102*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @use(ptr [[OBJ1]]) 10376dd98ecSAkira Hatanaka; CHECK-NEXT: br label [[JOIN]] 10476dd98ecSAkira Hatanaka; CHECK: join: 105*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @llvm.objc.release(ptr [[OBJ0]]) {{.*}}, !clang.imprecise_release !2 106*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @llvm.objc.release(ptr [[OBJ1]]) {{.*}}, !clang.imprecise_release !2 10776dd98ecSAkira Hatanaka; CHECK-NEXT: ret void 10876dd98ecSAkira Hatanaka; 109*01e4f41bSMatt Arsenault %v0 = call ptr @llvm.objc.retain(ptr %obj0) 110*01e4f41bSMatt Arsenault %v1 = call ptr @llvm.objc.retain(ptr %obj1) 11176dd98ecSAkira Hatanaka br i1 %cond, label %if.then, label %if.else 11276dd98ecSAkira Hatanaka 11376dd98ecSAkira Hatanakaif.then: 114*01e4f41bSMatt Arsenault call void @readOnlyFunc(ptr %obj0, ptr %obj1) #0 11576dd98ecSAkira Hatanaka add i32 1, 2 11676dd98ecSAkira Hatanaka call void @alterRefCount() 11776dd98ecSAkira Hatanaka br label %join 11876dd98ecSAkira Hatanaka 11976dd98ecSAkira Hatanakaif.else: 12076dd98ecSAkira Hatanaka call void @alterRefCount() 121*01e4f41bSMatt Arsenault call void @use(ptr %obj0) 122*01e4f41bSMatt Arsenault call void @use(ptr %obj1) 12376dd98ecSAkira Hatanaka br label %join 12476dd98ecSAkira Hatanaka 12576dd98ecSAkira Hatanakajoin: 126*01e4f41bSMatt Arsenault call void @llvm.objc.release(ptr %obj0), !clang.imprecise_release !9 127*01e4f41bSMatt Arsenault call void @llvm.objc.release(ptr %obj1), !clang.imprecise_release !9 12876dd98ecSAkira Hatanaka ret void 12976dd98ecSAkira Hatanaka} 13076dd98ecSAkira Hatanaka 131b931c2a7SAkira Hatanaka; In this test, insertion points for the retain and release calls that could be 132b931c2a7SAkira Hatanaka; eliminated are in different blocks (bb1 and if.then). 133b931c2a7SAkira Hatanaka 134*01e4f41bSMatt Arsenaultdefine void @test5(ptr %obj, i1 %cond0, i1 %cond1) { 135b931c2a7SAkira Hatanaka; CHECK-LABEL: @test5( 136*01e4f41bSMatt Arsenault; CHECK-NEXT: [[V0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ:%.*]]) 137b931c2a7SAkira Hatanaka; CHECK-NEXT: br i1 [[COND0:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 138b931c2a7SAkira Hatanaka; CHECK: if.then: 139*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @readOnlyFunc(ptr [[OBJ]], ptr null) 140b931c2a7SAkira Hatanaka; CHECK-NEXT: br i1 [[COND1:%.*]], label [[IF_THEN2:%.*]], label [[IF_ELSE2:%.*]] 141b931c2a7SAkira Hatanaka; CHECK: if.then2: 142b931c2a7SAkira Hatanaka; CHECK-NEXT: br label [[BB1:%.*]] 143b931c2a7SAkira Hatanaka; CHECK: if.else2: 144b931c2a7SAkira Hatanaka; CHECK-NEXT: br label [[BB1]] 145b931c2a7SAkira Hatanaka; CHECK: bb1: 146b931c2a7SAkira Hatanaka; CHECK-NEXT: [[TMP1:%.*]] = add i32 1, 2 147b931c2a7SAkira Hatanaka; CHECK-NEXT: call void @alterRefCount() 148b931c2a7SAkira Hatanaka; CHECK-NEXT: br label [[JOIN:%.*]] 149b931c2a7SAkira Hatanaka; CHECK: if.else: 150b931c2a7SAkira Hatanaka; CHECK-NEXT: call void @alterRefCount() 151*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @use(ptr [[OBJ]]) 152b931c2a7SAkira Hatanaka; CHECK-NEXT: br label [[JOIN]] 153b931c2a7SAkira Hatanaka; CHECK: join: 154*01e4f41bSMatt Arsenault; CHECK-NEXT: call void @llvm.objc.release(ptr [[OBJ]]) 155b931c2a7SAkira Hatanaka; CHECK-NEXT: ret void 156b931c2a7SAkira Hatanaka; 157*01e4f41bSMatt Arsenault %v0 = call ptr @llvm.objc.retain(ptr %obj) 158b931c2a7SAkira Hatanaka br i1 %cond0, label %if.then, label %if.else 159b931c2a7SAkira Hatanaka 160b931c2a7SAkira Hatanakaif.then: 161*01e4f41bSMatt Arsenault call void @readOnlyFunc(ptr %obj, ptr null) #0 162b931c2a7SAkira Hatanaka br i1 %cond1, label %if.then2, label %if.else2 163b931c2a7SAkira Hatanaka 164b931c2a7SAkira Hatanakaif.then2: 165b931c2a7SAkira Hatanaka br label %bb1 166b931c2a7SAkira Hatanaka 167b931c2a7SAkira Hatanakaif.else2: 168b931c2a7SAkira Hatanaka br label %bb1 169b931c2a7SAkira Hatanaka 170b931c2a7SAkira Hatanakabb1: 171b931c2a7SAkira Hatanaka add i32 1, 2 172b931c2a7SAkira Hatanaka call void @alterRefCount() 173b931c2a7SAkira Hatanaka br label %join 174b931c2a7SAkira Hatanaka 175b931c2a7SAkira Hatanakaif.else: 176b931c2a7SAkira Hatanaka call void @alterRefCount() 177*01e4f41bSMatt Arsenault call void @use(ptr %obj) 178b931c2a7SAkira Hatanaka br label %join 179b931c2a7SAkira Hatanaka 180b931c2a7SAkira Hatanakajoin: 181*01e4f41bSMatt Arsenault call void @llvm.objc.release(ptr %obj), !clang.imprecise_release !9 182b931c2a7SAkira Hatanaka ret void 183b931c2a7SAkira Hatanaka} 184b931c2a7SAkira Hatanaka 18575fbb171SAkira Hatanakadeclare void @llvm.dbg.declare(metadata, metadata, metadata) 186*01e4f41bSMatt Arsenaultdeclare ptr @llvm.objc.retain(ptr) local_unnamed_addr 187*01e4f41bSMatt Arsenaultdeclare void @llvm.objc.release(ptr) local_unnamed_addr 18875fbb171SAkira Hatanaka 18976dd98ecSAkira Hatanakaattributes #0 = { readonly } 19076dd98ecSAkira Hatanaka 19175fbb171SAkira Hatanaka!llvm.module.flags = !{!0, !1} 19275fbb171SAkira Hatanaka 19375fbb171SAkira Hatanaka!0 = !{i32 2, !"Dwarf Version", i32 4} 19475fbb171SAkira Hatanaka!1 = !{i32 2, !"Debug Info Version", i32 3} 19575fbb171SAkira Hatanaka!2 = !DILocalVariable(name: "i", arg: 1, scope: !3, file: !4, line: 1, type: !7) 19675fbb171SAkira Hatanaka!3 = distinct !DISubprogram(name: "test", scope: !4, file: !4, line: 1, type: !5, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !9) 19775fbb171SAkira Hatanaka!4 = !DIFile(filename: "test.m", directory: "dir") 19875fbb171SAkira Hatanaka!5 = !DISubroutineType(types: !6) 19975fbb171SAkira Hatanaka!6 = !{!7, !7} 20075fbb171SAkira Hatanaka!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 20175fbb171SAkira Hatanaka!8 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !4, isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !9, nameTableKind: None) 20275fbb171SAkira Hatanaka!9 = !{} 20375fbb171SAkira Hatanaka!10 = !DILocation(line: 1, column: 14, scope: !3) 204