xref: /llvm-project/llvm/test/Transforms/ObjCARC/code-motion.ll (revision 01e4f41b43b57dee751146fde9992c660bd7c714)
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