xref: /llvm-project/llvm/test/Transforms/ObjCARC/basic.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; RUN: opt -aa-pipeline=basic-aa -passes=objc-arc -S < %s | FileCheck %s
2
3target datalayout = "e-p:64:64:64"
4
5declare ptr @llvm.objc.retain(ptr)
6declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
7declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)
8declare void @llvm.objc.release(ptr)
9declare ptr @llvm.objc.autorelease(ptr)
10declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
11declare void @llvm.objc.autoreleasePoolPop(ptr)
12declare ptr @llvm.objc.autoreleasePoolPush()
13declare ptr @llvm.objc.retainBlock(ptr)
14
15declare ptr @llvm.objc.retainedObject(ptr)
16declare ptr @llvm.objc.unretainedObject(ptr)
17declare ptr @llvm.objc.unretainedPointer(ptr)
18
19declare void @use_pointer(ptr)
20declare void @callee()
21declare void @callee2(ptr, ptr)
22declare void @callee_fnptr(ptr)
23declare void @invokee()
24declare ptr @returner()
25declare void @bar(ptr)
26
27declare void @llvm.dbg.value(metadata, metadata, metadata)
28
29declare ptr @objc_msgSend(ptr, ptr, ...)
30
31; Simple retain+release pair deletion, with some intervening control
32; flow and harmless instructions.
33
34; CHECK: define void @test0_precise(ptr %x, i1 %p) [[NUW:#[0-9]+]] {
35; CHECK: @llvm.objc.retain
36; CHECK: @llvm.objc.release
37; CHECK: {{^}}}
38define void @test0_precise(ptr %x, i1 %p) nounwind {
39entry:
40  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
41  br i1 %p, label %t, label %f
42
43t:
44  store i8 3, ptr %x
45  store float 2.0, ptr %x
46  br label %return
47
48f:
49  store i32 7, ptr %x
50  br label %return
51
52return:
53  call void @llvm.objc.release(ptr %x) nounwind
54  ret void
55}
56
57; CHECK: define void @test0_imprecise(ptr %x, i1 %p) [[NUW]] {
58; CHECK-NOT: @llvm.objc.
59; CHECK: {{^}}}
60define void @test0_imprecise(ptr %x, i1 %p) nounwind {
61entry:
62  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
63  br i1 %p, label %t, label %f
64
65t:
66  store i8 3, ptr %x
67  store float 2.0, ptr %x
68  br label %return
69
70f:
71  store i32 7, ptr %x
72  br label %return
73
74return:
75  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
76  ret void
77}
78
79; Like test0 but the release isn't always executed when the retain is,
80; so the optimization is not safe.
81
82; TODO: Make the llvm.objc.release's argument be %0.
83
84; CHECK: define void @test1_precise(ptr %x, i1 %p, i1 %q) [[NUW]] {
85; CHECK: @llvm.objc.retain(ptr %x)
86; CHECK: @llvm.objc.release(ptr %x)
87; CHECK: {{^}}}
88define void @test1_precise(ptr %x, i1 %p, i1 %q) nounwind {
89entry:
90  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
91  br i1 %p, label %t, label %f
92
93t:
94  store i8 3, ptr %x
95  store float 2.0, ptr %x
96  br label %return
97
98f:
99  store i32 7, ptr %x
100  call void @callee()
101  br i1 %q, label %return, label %alt_return
102
103return:
104  call void @llvm.objc.release(ptr %x) nounwind
105  ret void
106
107alt_return:
108  ret void
109}
110
111; CHECK: define void @test1_imprecise(ptr %x, i1 %p, i1 %q) [[NUW]] {
112; CHECK: @llvm.objc.retain(ptr %x)
113; CHECK: @llvm.objc.release
114; CHECK: {{^}}}
115define void @test1_imprecise(ptr %x, i1 %p, i1 %q) nounwind {
116entry:
117  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
118  br i1 %p, label %t, label %f
119
120t:
121  store i8 3, ptr %x
122  store float 2.0, ptr %x
123  br label %return
124
125f:
126  store i32 7, ptr %x
127  call void @callee()
128  br i1 %q, label %return, label %alt_return
129
130return:
131  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
132  ret void
133
134alt_return:
135  ret void
136}
137
138
139; Don't do partial elimination into two different CFG diamonds.
140
141; CHECK: define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
142; CHECK: entry:
143; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
144; CHECK-NOT: @llvm.objc.
145; CHECK: if.end5:
146; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]]
147; CHECK-NOT: @llvm.objc.
148; CHECK: {{^}}}
149define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
150entry:
151  tail call ptr @llvm.objc.retain(ptr %x) nounwind
152  br i1 %p, label %if.then, label %if.end
153
154if.then:                                          ; preds = %entry
155  tail call void @callee()
156  br label %if.end
157
158if.end:                                           ; preds = %if.then, %entry
159  br i1 %q, label %if.then3, label %if.end5
160
161if.then3:                                         ; preds = %if.end
162  tail call void @use_pointer(ptr %x)
163  br label %if.end5
164
165if.end5:                                          ; preds = %if.then3, %if.end
166  tail call void @llvm.objc.release(ptr %x) nounwind
167  ret void
168}
169
170; CHECK-LABEL: define void @test1b_imprecise(
171; CHECK: entry:
172; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW:#[0-9]+]]
173; CHECK-NOT: @llvm.objc.
174; CHECK: if.end5:
175; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]]
176; CHECK-NOT: @llvm.objc.
177; CHECK: {{^}}}
178define void @test1b_imprecise(ptr %x, i1 %p, i1 %q) {
179entry:
180  tail call ptr @llvm.objc.retain(ptr %x) nounwind
181  br i1 %p, label %if.then, label %if.end
182
183if.then:                                          ; preds = %entry
184  tail call void @callee()
185  br label %if.end
186
187if.end:                                           ; preds = %if.then, %entry
188  br i1 %q, label %if.then3, label %if.end5
189
190if.then3:                                         ; preds = %if.end
191  tail call void @use_pointer(ptr %x)
192  br label %if.end5
193
194if.end5:                                          ; preds = %if.then3, %if.end
195  tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
196  ret void
197}
198
199
200; Like test0 but the pointer is passed to an intervening call,
201; so the optimization is not safe.
202
203; CHECK-LABEL: define void @test2_precise(
204; CHECK: @llvm.objc.retain(ptr %x)
205; CHECK: @llvm.objc.release
206; CHECK: {{^}}}
207define void @test2_precise(ptr %x, i1 %p) nounwind {
208entry:
209  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
210  br i1 %p, label %t, label %f
211
212t:
213  store i8 3, ptr %x
214  store float 2.0, ptr %x
215  br label %return
216
217f:
218  store i32 7, ptr %x
219  call void @use_pointer(ptr %0)
220  store float 3.0, ptr %x
221  br label %return
222
223return:
224  call void @llvm.objc.release(ptr %x) nounwind
225  ret void
226}
227
228; CHECK-LABEL: define void @test2_imprecise(
229; CHECK: @llvm.objc.retain(ptr %x)
230; CHECK: @llvm.objc.release
231; CHECK: {{^}}}
232define void @test2_imprecise(ptr %x, i1 %p) nounwind {
233entry:
234  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
235  br i1 %p, label %t, label %f
236
237t:
238  store i8 3, ptr %x
239  store float 2.0, ptr %x
240  br label %return
241
242f:
243  store i32 7, ptr %x
244  call void @use_pointer(ptr %0)
245  store float 3.0, ptr %x
246  br label %return
247
248return:
249  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
250  ret void
251}
252
253; Like test0 but the release is in a loop,
254; so the optimization is not safe.
255
256; TODO: For now, assume this can't happen.
257
258; CHECK-LABEL: define void @test3_precise(
259; TODO: @llvm.objc.retain(ptr %a)
260; TODO: @llvm.objc.release
261; CHECK: {{^}}}
262define void @test3_precise(ptr %x, ptr %q) nounwind {
263entry:
264  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
265  br label %loop
266
267loop:
268  call void @llvm.objc.release(ptr %x) nounwind
269  %j = load volatile i1, ptr %q
270  br i1 %j, label %loop, label %return
271
272return:
273  ret void
274}
275
276; CHECK-LABEL: define void @test3_imprecise(
277; TODO: @llvm.objc.retain(ptr %a)
278; TODO: @llvm.objc.release
279; CHECK: {{^}}}
280define void @test3_imprecise(ptr %x, ptr %q) nounwind {
281entry:
282  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
283  br label %loop
284
285loop:
286  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
287  %j = load volatile i1, ptr %q
288  br i1 %j, label %loop, label %return
289
290return:
291  ret void
292}
293
294
295; TODO: For now, assume this can't happen.
296
297; Like test0 but the retain is in a loop,
298; so the optimization is not safe.
299
300; CHECK-LABEL: define void @test4_precise(
301; TODO: @llvm.objc.retain(ptr %a)
302; TODO: @llvm.objc.release
303; CHECK: {{^}}}
304define void @test4_precise(ptr %x, ptr %q) nounwind {
305entry:
306  br label %loop
307
308loop:
309  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
310  %j = load volatile i1, ptr %q
311  br i1 %j, label %loop, label %return
312
313return:
314  call void @llvm.objc.release(ptr %x) nounwind
315  ret void
316}
317
318; CHECK-LABEL: define void @test4_imprecise(
319; TODO: @llvm.objc.retain(ptr %a)
320; TODO: @llvm.objc.release
321; CHECK: {{^}}}
322define void @test4_imprecise(ptr %x, ptr %q) nounwind {
323entry:
324  br label %loop
325
326loop:
327  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
328  %j = load volatile i1, ptr %q
329  br i1 %j, label %loop, label %return
330
331return:
332  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
333  ret void
334}
335
336
337; Like test0 but the pointer is conditionally passed to an intervening call,
338; so the optimization is not safe.
339
340; CHECK-LABEL: define void @test5a(
341; CHECK: @llvm.objc.retain(ptr
342; CHECK: @llvm.objc.release
343; CHECK: {{^}}}
344define void @test5a(ptr %x, i1 %q, ptr %y) nounwind {
345entry:
346  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
347  %s = select i1 %q, ptr %y, ptr %0
348  call void @use_pointer(ptr %s)
349  store i32 7, ptr %x
350  call void @llvm.objc.release(ptr %x) nounwind
351  ret void
352}
353
354; CHECK-LABEL: define void @test5b(
355; CHECK: @llvm.objc.retain(ptr
356; CHECK: @llvm.objc.release
357; CHECK: {{^}}}
358define void @test5b(ptr %x, i1 %q, ptr %y) nounwind {
359entry:
360  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
361  %s = select i1 %q, ptr %y, ptr %0
362  call void @use_pointer(ptr %s)
363  store i32 7, ptr %x
364  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
365  ret void
366}
367
368
369; retain+release pair deletion, where the release happens on two different
370; flow paths.
371
372; CHECK-LABEL: define void @test6a(
373; CHECK: entry:
374; CHECK:   tail call ptr @llvm.objc.retain
375; CHECK: t:
376; CHECK:   call void @llvm.objc.release
377; CHECK: f:
378; CHECK:   call void @llvm.objc.release
379; CHECK: return:
380; CHECK: {{^}}}
381define void @test6a(ptr %x, i1 %p) nounwind {
382entry:
383  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
384  br i1 %p, label %t, label %f
385
386t:
387  store i8 3, ptr %x
388  store float 2.0, ptr %x
389  call void @llvm.objc.release(ptr %x) nounwind
390  br label %return
391
392f:
393  store i32 7, ptr %x
394  call void @callee()
395  call void @llvm.objc.release(ptr %x) nounwind
396  br label %return
397
398return:
399  ret void
400}
401
402; CHECK-LABEL: define void @test6b(
403; CHECK-NOT: @llvm.objc.
404; CHECK: {{^}}}
405define void @test6b(ptr %x, i1 %p) nounwind {
406entry:
407  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
408  br i1 %p, label %t, label %f
409
410t:
411  store i8 3, ptr %x
412  store float 2.0, ptr %x
413  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
414  br label %return
415
416f:
417  store i32 7, ptr %x
418  call void @callee()
419  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
420  br label %return
421
422return:
423  ret void
424}
425
426; CHECK-LABEL: define void @test6c(
427; CHECK: entry:
428; CHECK:   tail call ptr @llvm.objc.retain
429; CHECK: t:
430; CHECK:   call void @llvm.objc.release
431; CHECK: f:
432; CHECK:   call void @llvm.objc.release
433; CHECK: return:
434; CHECK: {{^}}}
435define void @test6c(ptr %x, i1 %p) nounwind {
436entry:
437  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
438  br i1 %p, label %t, label %f
439
440t:
441  store i8 3, ptr %x
442  store float 2.0, ptr %x
443  call void @llvm.objc.release(ptr %x) nounwind
444  br label %return
445
446f:
447  store i32 7, ptr %x
448  call void @callee()
449  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
450  br label %return
451
452return:
453  ret void
454}
455
456; CHECK-LABEL: define void @test6d(
457; CHECK: entry:
458; CHECK:   tail call ptr @llvm.objc.retain
459; CHECK: t:
460; CHECK:   call void @llvm.objc.release
461; CHECK: f:
462; CHECK:   call void @llvm.objc.release
463; CHECK: return:
464; CHECK: {{^}}}
465define void @test6d(ptr %x, i1 %p) nounwind {
466entry:
467  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
468  br i1 %p, label %t, label %f
469
470t:
471  store i8 3, ptr %x
472  store float 2.0, ptr %x
473  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
474  br label %return
475
476f:
477  store i32 7, ptr %x
478  call void @callee()
479  call void @llvm.objc.release(ptr %x) nounwind
480  br label %return
481
482return:
483  ret void
484}
485
486
487; retain+release pair deletion, where the retain happens on two different
488; flow paths.
489
490; CHECK-LABEL:     define void @test7(
491; CHECK:     entry:
492; CHECK-NOT:   llvm.objc.
493; CHECK:     t:
494; CHECK:       call ptr @llvm.objc.retain
495; CHECK:     f:
496; CHECK:       call ptr @llvm.objc.retain
497; CHECK:     return:
498; CHECK:       call void @llvm.objc.release
499; CHECK: {{^}}}
500define void @test7(ptr %x, i1 %p) nounwind {
501entry:
502  br i1 %p, label %t, label %f
503
504t:
505  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
506  store i8 3, ptr %x
507  store float 2.0, ptr %x
508  br label %return
509
510f:
511  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
512  store i32 7, ptr %x
513  call void @callee()
514  br label %return
515
516return:
517  call void @llvm.objc.release(ptr %x) nounwind
518  ret void
519}
520
521; CHECK-LABEL: define void @test7b(
522; CHECK-NOT: @llvm.objc.
523; CHECK: {{^}}}
524define void @test7b(ptr %x, i1 %p) nounwind {
525entry:
526  br i1 %p, label %t, label %f
527
528t:
529  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
530  store i8 3, ptr %x
531  store float 2.0, ptr %x
532  br label %return
533
534f:
535  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
536  store i32 7, ptr %x
537  call void @callee()
538  br label %return
539
540return:
541  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
542  ret void
543}
544
545; Like test7, but there's a retain/retainBlock mismatch. Don't delete!
546
547; CHECK-LABEL: define void @test7c(
548; CHECK: t:
549; CHECK:   call ptr @llvm.objc.retainBlock
550; CHECK: f:
551; CHECK:   call ptr @llvm.objc.retain
552; CHECK: return:
553; CHECK:   call void @llvm.objc.release
554; CHECK: {{^}}}
555define void @test7c(ptr %x, i1 %p) nounwind {
556entry:
557  br i1 %p, label %t, label %f
558
559t:
560  %0 = call ptr @llvm.objc.retainBlock(ptr %x) nounwind
561  store i8 3, ptr %x
562  store float 2.0, ptr %x
563  br label %return
564
565f:
566  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
567  store i32 7, ptr %x
568  call void @callee()
569  br label %return
570
571return:
572  call void @llvm.objc.release(ptr %x) nounwind
573  ret void
574}
575
576; retain+release pair deletion, where the retain and release both happen on
577; different flow paths. Wild!
578
579; CHECK-LABEL: define void @test8a(
580; CHECK: entry:
581; CHECK: t:
582; CHECK:   @llvm.objc.retain
583; CHECK: f:
584; CHECK:   @llvm.objc.retain
585; CHECK: mid:
586; CHECK: u:
587; CHECK:   @llvm.objc.release
588; CHECK: g:
589; CHECK:   @llvm.objc.release
590; CHECK: return:
591; CHECK: {{^}}}
592define void @test8a(ptr %x, i1 %p, i1 %q) nounwind {
593entry:
594  br i1 %p, label %t, label %f
595
596t:
597  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
598  store i8 3, ptr %x
599  store float 2.0, ptr %x
600  br label %mid
601
602f:
603  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
604  store i32 7, ptr %x
605  br label %mid
606
607mid:
608  br i1 %q, label %u, label %g
609
610u:
611  call void @callee()
612  call void @llvm.objc.release(ptr %x) nounwind
613  br label %return
614
615g:
616  call void @llvm.objc.release(ptr %x) nounwind
617  br label %return
618
619return:
620  ret void
621}
622
623; CHECK-LABEL: define void @test8b(
624; CHECK-NOT: @llvm.objc.
625; CHECK: {{^}}}
626define void @test8b(ptr %x, i1 %p, i1 %q) nounwind {
627entry:
628  br i1 %p, label %t, label %f
629
630t:
631  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
632  store i8 3, ptr %x
633  store float 2.0, ptr %x
634  br label %mid
635
636f:
637  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
638  store i32 7, ptr %x
639  br label %mid
640
641mid:
642  br i1 %q, label %u, label %g
643
644u:
645  call void @callee()
646  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
647  br label %return
648
649g:
650  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
651  br label %return
652
653return:
654  ret void
655}
656
657; CHECK-LABEL: define void @test8c(
658; CHECK: entry:
659; CHECK: t:
660; CHECK-NOT: @llvm.objc.
661; CHECK: f:
662; CHECK-NOT: @llvm.objc.
663; CHECK: mid:
664; CHECK: u:
665; CHECK:   @llvm.objc.retain
666; CHECK:   @llvm.objc.release
667; CHECK: g:
668; CHECK-NOT: @llvm.objc.
669; CHECK: return:
670; CHECK: {{^}}}
671define void @test8c(ptr %x, i1 %p, i1 %q) nounwind {
672entry:
673  br i1 %p, label %t, label %f
674
675t:
676  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
677  store i8 3, ptr %x
678  store float 2.0, ptr %x
679  br label %mid
680
681f:
682  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
683  store i32 7, ptr %x
684  br label %mid
685
686mid:
687  br i1 %q, label %u, label %g
688
689u:
690  call void @callee()
691  call void @llvm.objc.release(ptr %x) nounwind
692  br label %return
693
694g:
695  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
696  br label %return
697
698return:
699  ret void
700}
701
702; CHECK-LABEL: define void @test8d(
703; CHECK: entry:
704; CHECK: t:
705; CHECK:   @llvm.objc.retain
706; CHECK: f:
707; CHECK:   @llvm.objc.retain
708; CHECK: mid:
709; CHECK: u:
710; CHECK:   @llvm.objc.release
711; CHECK: g:
712; CHECK:   @llvm.objc.release
713; CHECK: return:
714; CHECK: {{^}}}
715define void @test8d(ptr %x, i1 %p, i1 %q) nounwind {
716entry:
717  br i1 %p, label %t, label %f
718
719t:
720  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
721  store i8 3, ptr %x
722  store float 2.0, ptr %x
723  br label %mid
724
725f:
726  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
727  store i32 7, ptr %x
728  br label %mid
729
730mid:
731  br i1 %q, label %u, label %g
732
733u:
734  call void @callee()
735  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
736  br label %return
737
738g:
739  call void @llvm.objc.release(ptr %x) nounwind
740  br label %return
741
742return:
743  ret void
744}
745
746; Trivial retain+release pair deletion.
747
748; CHECK-LABEL: define void @test9(
749; CHECK-NOT: @llvm.objc.
750; CHECK: {{^}}}
751define void @test9(ptr %x) nounwind {
752entry:
753  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
754  call void @llvm.objc.release(ptr %0) nounwind
755  ret void
756}
757
758; Retain+release pair, but on an unknown pointer relationship. Don't delete!
759
760; CHECK-LABEL: define void @test9b(
761; CHECK: @llvm.objc.retain(ptr %x)
762; CHECK: @llvm.objc.release(ptr %s)
763; CHECK: {{^}}}
764define void @test9b(ptr %x, i1 %j, ptr %p) nounwind {
765entry:
766  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
767  %s = select i1 %j, ptr %x, ptr %p
768  call void @llvm.objc.release(ptr %s) nounwind
769  ret void
770}
771
772; Trivial retain+release pair with intervening calls - don't delete!
773
774; CHECK-LABEL: define void @test10(
775; CHECK: @llvm.objc.retain(ptr %x)
776; CHECK: @callee
777; CHECK: @use_pointer
778; CHECK: @llvm.objc.release
779; CHECK: {{^}}}
780define void @test10(ptr %x) nounwind {
781entry:
782  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
783  call void @callee()
784  call void @use_pointer(ptr %x)
785  call void @llvm.objc.release(ptr %0) nounwind
786  ret void
787}
788
789; Trivial retain+autoreleaserelease pair. Don't delete!
790; Also, add a tail keyword, since llvm.objc.retain can never be passed
791; a stack argument.
792
793; CHECK-LABEL: define void @test11(
794; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
795; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]
796; CHECK: {{^}}}
797define void @test11(ptr %x) nounwind {
798entry:
799  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
800  call ptr @llvm.objc.autorelease(ptr %0) nounwind
801  call void @use_pointer(ptr %x)
802  ret void
803}
804
805; Same as test11 but with no use_pointer call. Delete the pair!
806
807; CHECK-LABEL: define void @test11a(
808; CHECK: entry:
809; CHECK-NEXT: ret void
810; CHECK: {{^}}}
811define void @test11a(ptr %x) nounwind {
812entry:
813  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
814  call ptr @llvm.objc.autorelease(ptr %0) nounwind
815  ret void
816}
817
818; Same as test11 but the value is returned. Do not perform an RV optimization
819; since if the frontend emitted code for an __autoreleasing variable, we may
820; want it to be in the autorelease pool.
821
822; CHECK-LABEL: define ptr @test11b(
823; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
824; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]
825; CHECK: {{^}}}
826define ptr @test11b(ptr %x) nounwind {
827entry:
828  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
829  call ptr @llvm.objc.autorelease(ptr %0) nounwind
830  ret ptr %x
831}
832
833; We can not delete this retain, release since we do not have a post-dominating
834; use of the release.
835
836; CHECK-LABEL: define void @test12(
837; CHECK-NEXT: entry:
838; CHECK-NEXT: @llvm.objc.retain(ptr %x)
839; CHECK-NEXT: @llvm.objc.retain
840; CHECK: @llvm.objc.release
841; CHECK: {{^}}}
842define void @test12(ptr %x, i64 %n) {
843entry:
844  call ptr @llvm.objc.retain(ptr %x) nounwind
845  call ptr @llvm.objc.retain(ptr %x) nounwind
846  call void @use_pointer(ptr %x)
847  call void @use_pointer(ptr %x)
848  call void @llvm.objc.release(ptr %x) nounwind
849  ret void
850}
851
852; Trivial retain,autorelease pair. Don't delete!
853
854; CHECK-LABEL: define void @test13(
855; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
856; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
857; CHECK: @use_pointer(ptr %x)
858; CHECK: call ptr @llvm.objc.autorelease(ptr %x) [[NUW]]
859; CHECK: {{^}}}
860define void @test13(ptr %x, i64 %n) {
861entry:
862  call ptr @llvm.objc.retain(ptr %x) nounwind
863  call ptr @llvm.objc.retain(ptr %x) nounwind
864  call void @use_pointer(ptr %x)
865  call ptr @llvm.objc.autorelease(ptr %x) nounwind
866  ret void
867}
868
869; Delete the retain+release pair.
870
871; CHECK-LABEL: define void @test13b(
872; CHECK-NEXT: entry:
873; CHECK-NEXT: @llvm.objc.retain(ptr %x)
874; CHECK-NEXT: @use_pointer
875; CHECK-NEXT: @use_pointer
876; CHECK-NEXT: @use_pointer
877; CHECK-NEXT: @llvm.objc.release
878; CHECK-NEXT: ret void
879; CHECK-NEXT: }
880define void @test13b(ptr %x, i64 %n) {
881entry:
882  call ptr @llvm.objc.retain(ptr %x) nounwind
883  call ptr @llvm.objc.retain(ptr %x) nounwind
884  call void @use_pointer(ptr %x)
885  call void @use_pointer(ptr %x)
886  call void @llvm.objc.release(ptr %x) nounwind
887  call void @use_pointer(ptr %x)
888  call void @llvm.objc.release(ptr %x) nounwind
889  ret void
890}
891
892; Don't delete the retain+release pair because there's an
893; autoreleasePoolPop in the way.
894
895; CHECK-LABEL: define void @test13c(
896; CHECK: @llvm.objc.retain(ptr %x)
897; CHECK: @llvm.objc.autoreleasePoolPop
898; CHECK: @llvm.objc.retain(ptr %x)
899; CHECK: @use_pointer
900; CHECK: @llvm.objc.release
901; CHECK: {{^}}}
902define void @test13c(ptr %x, i64 %n) {
903entry:
904  call ptr @llvm.objc.retain(ptr %x) nounwind
905  call void @llvm.objc.autoreleasePoolPop(ptr undef)
906  call ptr @llvm.objc.retain(ptr %x) nounwind
907  call void @use_pointer(ptr %x)
908  call void @use_pointer(ptr %x)
909  call void @llvm.objc.release(ptr %x) nounwind
910  ret void
911}
912
913; Like test13c, but there's an autoreleasePoolPush in the way, but that
914; doesn't matter.
915
916; CHECK-LABEL: define void @test13d(
917; CHECK-NEXT: entry:
918; CHECK-NEXT: @llvm.objc.retain(ptr %x)
919; CHECK-NEXT: @llvm.objc.autoreleasePoolPush
920; CHECK-NEXT: @use_pointer
921; CHECK-NEXT: @use_pointer
922; CHECK-NEXT: @use_pointer
923; CHECK-NEXT: @llvm.objc.release
924; CHECK-NEXT: ret void
925; CHECK-NEXT: }
926define void @test13d(ptr %x, i64 %n) {
927entry:
928  call ptr @llvm.objc.retain(ptr %x) nounwind
929  call ptr @llvm.objc.autoreleasePoolPush()
930  call ptr @llvm.objc.retain(ptr %x) nounwind
931  call void @use_pointer(ptr %x)
932  call void @use_pointer(ptr %x)
933  call void @llvm.objc.release(ptr %x) nounwind
934  call void @use_pointer(ptr %x)
935  call void @llvm.objc.release(ptr %x) nounwind
936  ret void
937}
938
939; Trivial retain,release pair with intervening call, and it's post-dominated by
940; another release. But it is not known safe in the top down direction. We can
941; not eliminate it.
942
943; CHECK-LABEL: define void @test14(
944; CHECK-NEXT: entry:
945; CHECK-NEXT: @llvm.objc.retain
946; CHECK-NEXT: @use_pointer
947; CHECK-NEXT: @use_pointer
948; CHECK-NEXT: @llvm.objc.release
949; CHECK-NEXT: @llvm.objc.release
950; CHECK-NEXT: ret void
951; CHECK-NEXT: }
952define void @test14(ptr %x, i64 %n) {
953entry:
954  call ptr @llvm.objc.retain(ptr %x) nounwind
955  call void @use_pointer(ptr %x)
956  call void @use_pointer(ptr %x)
957  call void @llvm.objc.release(ptr %x) nounwind
958  call void @llvm.objc.release(ptr %x) nounwind
959  ret void
960}
961
962; Trivial retain,autorelease pair with intervening call, but it's post-dominated
963; by another release. Don't delete anything.
964
965; CHECK-LABEL: define void @test15(
966; CHECK-NEXT: entry:
967; CHECK-NEXT: @llvm.objc.retain(ptr %x)
968; CHECK-NEXT: @use_pointer
969; CHECK-NEXT: @llvm.objc.autorelease(ptr %x)
970; CHECK-NEXT: @llvm.objc.release
971; CHECK-NEXT: ret void
972; CHECK-NEXT: }
973define void @test15(ptr %x, i64 %n) {
974entry:
975  call ptr @llvm.objc.retain(ptr %x) nounwind
976  call void @use_pointer(ptr %x)
977  call ptr @llvm.objc.autorelease(ptr %x) nounwind
978  call void @llvm.objc.release(ptr %x) nounwind
979  ret void
980}
981
982; Trivial retain,autorelease pair, post-dominated
983; by another release. Delete the retain and release.
984
985; CHECK-LABEL: define void @test15b(
986; CHECK-NEXT: entry:
987; CHECK-NEXT: @llvm.objc.retain
988; CHECK-NEXT: @llvm.objc.autorelease
989; CHECK-NEXT: @llvm.objc.release
990; CHECK-NEXT: ret void
991; CHECK-NEXT: }
992define void @test15b(ptr %x, i64 %n) {
993entry:
994  call ptr @llvm.objc.retain(ptr %x) nounwind
995  call ptr @llvm.objc.autorelease(ptr %x) nounwind
996  call void @llvm.objc.release(ptr %x) nounwind
997  ret void
998}
999
1000; CHECK-LABEL: define void @test15c(
1001; CHECK-NEXT: entry:
1002; CHECK-NEXT: @llvm.objc.autorelease
1003; CHECK-NEXT: ret void
1004; CHECK-NEXT: }
1005define void @test15c(ptr %x, i64 %n) {
1006entry:
1007  call ptr @llvm.objc.retain(ptr %x) nounwind
1008  call ptr @llvm.objc.autorelease(ptr %x) nounwind
1009  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1010  ret void
1011}
1012
1013; Retain+release pairs in diamonds, all dominated by a retain.
1014
1015; CHECK-LABEL: define void @test16a(
1016; CHECK: @llvm.objc.retain(ptr %x)
1017; CHECK-NOT: @objc
1018; CHECK: purple:
1019; CHECK: @use_pointer
1020; CHECK: @llvm.objc.release
1021; CHECK: {{^}}}
1022define void @test16a(i1 %a, i1 %b, ptr %x) {
1023entry:
1024  call ptr @llvm.objc.retain(ptr %x) nounwind
1025  br i1 %a, label %red, label %orange
1026
1027red:
1028  call ptr @llvm.objc.retain(ptr %x) nounwind
1029  br label %yellow
1030
1031orange:
1032  call ptr @llvm.objc.retain(ptr %x) nounwind
1033  br label %yellow
1034
1035yellow:
1036  call void @use_pointer(ptr %x)
1037  call void @use_pointer(ptr %x)
1038  br i1 %b, label %green, label %blue
1039
1040green:
1041  call void @llvm.objc.release(ptr %x) nounwind
1042  br label %purple
1043
1044blue:
1045  call void @llvm.objc.release(ptr %x) nounwind
1046  br label %purple
1047
1048purple:
1049  call void @use_pointer(ptr %x)
1050  call void @llvm.objc.release(ptr %x) nounwind
1051  ret void
1052}
1053
1054; CHECK-LABEL: define void @test16b(
1055; CHECK: @llvm.objc.retain(ptr %x)
1056; CHECK-NOT: @objc
1057; CHECK: purple:
1058; CHECK-NEXT: @use_pointer
1059; CHECK-NEXT: @use_pointer
1060; CHECK-NEXT: @llvm.objc.release
1061; CHECK: {{^}}}
1062define void @test16b(i1 %a, i1 %b, ptr %x) {
1063entry:
1064  call ptr @llvm.objc.retain(ptr %x) nounwind
1065  br i1 %a, label %red, label %orange
1066
1067red:
1068  call ptr @llvm.objc.retain(ptr %x) nounwind
1069  br label %yellow
1070
1071orange:
1072  call ptr @llvm.objc.retain(ptr %x) nounwind
1073  br label %yellow
1074
1075yellow:
1076  call void @use_pointer(ptr %x)
1077  call void @use_pointer(ptr %x)
1078  br i1 %b, label %green, label %blue
1079
1080green:
1081  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1082  br label %purple
1083
1084blue:
1085  call void @llvm.objc.release(ptr %x) nounwind
1086  br label %purple
1087
1088purple:
1089  call void @use_pointer(ptr %x)
1090  call void @use_pointer(ptr %x)
1091  call void @llvm.objc.release(ptr %x) nounwind
1092  ret void
1093}
1094
1095; CHECK-LABEL: define void @test16c(
1096; CHECK: @llvm.objc.retain(ptr %x)
1097; CHECK-NOT: @objc
1098; CHECK: purple:
1099; CHECK: @use_pointer
1100; CHECK: @llvm.objc.release
1101; CHECK: {{^}}}
1102define void @test16c(i1 %a, i1 %b, ptr %x) {
1103entry:
1104  call ptr @llvm.objc.retain(ptr %x) nounwind
1105  br i1 %a, label %red, label %orange
1106
1107red:
1108  call ptr @llvm.objc.retain(ptr %x) nounwind
1109  br label %yellow
1110
1111orange:
1112  call ptr @llvm.objc.retain(ptr %x) nounwind
1113  br label %yellow
1114
1115yellow:
1116  call void @use_pointer(ptr %x)
1117  call void @use_pointer(ptr %x)
1118  br i1 %b, label %green, label %blue
1119
1120green:
1121  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1122  br label %purple
1123
1124blue:
1125  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1126  br label %purple
1127
1128purple:
1129  call void @use_pointer(ptr %x)
1130  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1131  ret void
1132}
1133
1134; CHECK-LABEL: define void @test16d(
1135; CHECK: @llvm.objc.retain(ptr %x)
1136; CHECK: @llvm.objc
1137; CHECK: {{^}}}
1138define void @test16d(i1 %a, i1 %b, ptr %x) {
1139entry:
1140  call ptr @llvm.objc.retain(ptr %x) nounwind
1141  br i1 %a, label %red, label %orange
1142
1143red:
1144  call ptr @llvm.objc.retain(ptr %x) nounwind
1145  br label %yellow
1146
1147orange:
1148  call ptr @llvm.objc.retain(ptr %x) nounwind
1149  br label %yellow
1150
1151yellow:
1152  call void @use_pointer(ptr %x)
1153  call void @use_pointer(ptr %x)
1154  br i1 %b, label %green, label %blue
1155
1156green:
1157  call void @llvm.objc.release(ptr %x) nounwind
1158  br label %purple
1159
1160blue:
1161  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1162  br label %purple
1163
1164purple:
1165  ret void
1166}
1167
1168; Delete no-ops.
1169
1170; CHECK-LABEL: define void @test18(
1171; CHECK-NOT: @llvm.objc.
1172; CHECK: {{^}}}
1173define void @test18() {
1174  call ptr @llvm.objc.retain(ptr null)
1175  call void @llvm.objc.release(ptr null)
1176  call ptr @llvm.objc.autorelease(ptr null)
1177  ret void
1178}
1179
1180; Delete no-ops where undef can be assumed to be null.
1181
1182; CHECK-LABEL: define void @test18b(
1183; CHECK-NOT: @llvm.objc.
1184; CHECK: {{^}}}
1185define void @test18b() {
1186  call ptr @llvm.objc.retain(ptr undef)
1187  call void @llvm.objc.release(ptr undef)
1188  call ptr @llvm.objc.autorelease(ptr undef)
1189  ret void
1190}
1191
1192; Replace uses of arguments with uses of return values, to reduce
1193; register pressure.
1194
1195; CHECK: define void @test19(ptr %y) {
1196; CHECK:   %0 = tail call ptr @llvm.objc.retain(ptr %y)
1197; CHECK:   call void @use_pointer(ptr %y)
1198; CHECK:   call void @use_pointer(ptr %y)
1199; CHECK:   call void @llvm.objc.release(ptr %y)
1200; CHECK:   ret void
1201; CHECK: {{^}}}
1202define void @test19(ptr %y) {
1203entry:
1204  %0 = call ptr @llvm.objc.retain(ptr %y) nounwind
1205  call void @use_pointer(ptr %y)
1206  call void @use_pointer(ptr %y)
1207  call void @llvm.objc.release(ptr %y)
1208  ret void
1209}
1210
1211; Bitcast insertion
1212
1213; CHECK-LABEL: define void @test20(
1214; CHECK: %tmp1 = tail call ptr @llvm.objc.retain(ptr %self) [[NUW]]
1215; CHECK-NEXT: invoke
1216; CHECK: {{^}}}
1217define void @test20(ptr %self) personality ptr @__gxx_personality_v0 {
1218if.then12:
1219  %tmp1 = call ptr @llvm.objc.retain(ptr %self) nounwind
1220  invoke void @invokee()
1221          to label %invoke.cont23 unwind label %lpad20
1222
1223invoke.cont23:                                    ; preds = %if.then12
1224  invoke void @invokee()
1225          to label %if.end unwind label %lpad20
1226
1227lpad20:                                           ; preds = %invoke.cont23, %if.then12
1228  %tmp502 = phi ptr [ undef, %invoke.cont23 ], [ %self, %if.then12 ]
1229  %exn = landingpad {ptr, i32}
1230           cleanup
1231  unreachable
1232
1233if.end:                                           ; preds = %invoke.cont23
1234  ret void
1235}
1236
1237; Delete a redundant retain,autorelease when forwaring a call result
1238; directly to a return value.
1239
1240; CHECK-LABEL: define ptr @test21(
1241; CHECK: call ptr @returner()
1242; CHECK-NEXT: ret ptr %call
1243; CHECK-NEXT: }
1244define ptr @test21() {
1245entry:
1246  %call = call ptr @returner()
1247  %0 = call ptr @llvm.objc.retain(ptr %call) nounwind
1248  %1 = call ptr @llvm.objc.autorelease(ptr %0) nounwind
1249  ret ptr %1
1250}
1251
1252; Move an objc call up through a phi that has null operands.
1253
1254; CHECK-LABEL: define void @test22(
1255; CHECK: B:
1256; CHECK:   call void @llvm.objc.release(ptr %p)
1257; CHECK:   br label %C
1258; CHECK: C:                                                ; preds = %B, %A
1259; CHECK-NOT: @llvm.objc.release
1260; CHECK: {{^}}}
1261define void @test22(ptr %p, i1 %a) {
1262  br i1 %a, label %A, label %B
1263A:
1264  br label %C
1265B:
1266  br label %C
1267C:
1268  %h = phi ptr [ null, %A ], [ %p, %B ]
1269  call void @llvm.objc.release(ptr %h), !clang.imprecise_release !0
1270  ret void
1271}
1272
1273; Do not move an llvm.objc.release that doesn't have the clang.imprecise_release tag.
1274
1275; CHECK-LABEL: define void @test22_precise(
1276; CHECK: %[[P0:.*]] = phi ptr
1277; CHECK: call void @llvm.objc.release(ptr %[[P0]])
1278; CHECK: ret void
1279define void @test22_precise(ptr %p, i1 %a) {
1280  br i1 %a, label %A, label %B
1281A:
1282  br label %C
1283B:
1284  br label %C
1285C:
1286  %h = phi ptr [ null, %A ], [ %p, %B ]
1287  call void @llvm.objc.release(ptr %h)
1288  ret void
1289}
1290
1291; Any call can decrement a retain count.
1292
1293; CHECK-LABEL: define void @test24(
1294; CHECK: @llvm.objc.retain(ptr %a)
1295; CHECK: @llvm.objc.release
1296; CHECK: {{^}}}
1297define void @test24(ptr %r, ptr %a) {
1298  call ptr @llvm.objc.retain(ptr %a)
1299  call void @use_pointer(ptr %r)
1300  %q = load i8, ptr %a
1301  call void @llvm.objc.release(ptr %a)
1302  ret void
1303}
1304
1305; Don't move a retain/release pair if the release can be moved
1306; but the retain can't be moved to balance it.
1307
1308; CHECK-LABEL: define void @test25(
1309; CHECK: entry:
1310; CHECK:   call ptr @llvm.objc.retain(ptr %p)
1311; CHECK: true:
1312; CHECK: done:
1313; CHECK:   call void @llvm.objc.release(ptr %p)
1314; CHECK: {{^}}}
1315define void @test25(ptr %p, i1 %x) {
1316entry:
1317  %f0 = call ptr @llvm.objc.retain(ptr %p)
1318  call void @callee()
1319  br i1 %x, label %true, label %done
1320
1321true:
1322  store i8 0, ptr %p
1323  br label %done
1324
1325done:
1326  call void @llvm.objc.release(ptr %p)
1327  ret void
1328}
1329
1330; Don't move a retain/release pair if the retain can be moved
1331; but the release can't be moved to balance it.
1332
1333; CHECK-LABEL: define void @test26(
1334; CHECK: entry:
1335; CHECK:   call ptr @llvm.objc.retain(ptr %p)
1336; CHECK: true:
1337; CHECK: done:
1338; CHECK:   call void @llvm.objc.release(ptr %p)
1339; CHECK: {{^}}}
1340define void @test26(ptr %p, i1 %x) {
1341entry:
1342  %f0 = call ptr @llvm.objc.retain(ptr %p)
1343  br i1 %x, label %true, label %done
1344
1345true:
1346  call void @callee()
1347  br label %done
1348
1349done:
1350  store i8 0, ptr %p
1351  call void @llvm.objc.release(ptr %p)
1352  ret void
1353}
1354
1355; Don't sink the retain,release into the loop.
1356
1357; CHECK-LABEL: define void @test27(
1358; CHECK: entry:
1359; CHECK: call ptr @llvm.objc.retain(ptr %p)
1360; CHECK: loop:
1361; CHECK-NOT: @llvm.objc.
1362; CHECK: done:
1363; CHECK: call void @llvm.objc.release
1364; CHECK: {{^}}}
1365define void @test27(ptr %p, i1 %x, i1 %y) {
1366entry:
1367  %f0 = call ptr @llvm.objc.retain(ptr %p)
1368  br i1 %x, label %loop, label %done
1369
1370loop:
1371  call void @callee()
1372  store i8 0, ptr %p
1373  br i1 %y, label %done, label %loop
1374
1375done:
1376  call void @llvm.objc.release(ptr %p)
1377  ret void
1378}
1379
1380; Trivial code motion case: Triangle.
1381
1382; CHECK-LABEL: define void @test28(
1383; CHECK-NOT: @llvm.objc.
1384; CHECK: true:
1385; CHECK: call ptr @llvm.objc.retain
1386; CHECK: call void @callee()
1387; CHECK: store
1388; CHECK: call void @llvm.objc.release
1389; CHECK: done:
1390; CHECK-NOT: @llvm.objc.
1391; CHECK: {{^}}}
1392define void @test28(ptr %p, i1 %x) {
1393entry:
1394  %f0 = call ptr @llvm.objc.retain(ptr %p)
1395  br i1 %x, label %true, label %done
1396
1397true:
1398  call void @callee()
1399  store i8 0, ptr %p
1400  br label %done
1401
1402done:
1403  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1404  ret void
1405}
1406
1407; Trivial code motion case: Triangle, but no metadata. Don't move past
1408; unrelated memory references!
1409
1410; CHECK-LABEL: define void @test28b(
1411; CHECK: call ptr @llvm.objc.retain
1412; CHECK: true:
1413; CHECK-NOT: @llvm.objc.
1414; CHECK: call void @callee()
1415; CHECK-NOT: @llvm.objc.
1416; CHECK: store
1417; CHECK-NOT: @llvm.objc.
1418; CHECK: done:
1419; CHECK: @llvm.objc.release
1420; CHECK: {{^}}}
1421define void @test28b(ptr %p, i1 %x, ptr noalias %t) {
1422entry:
1423  %f0 = call ptr @llvm.objc.retain(ptr %p)
1424  br i1 %x, label %true, label %done
1425
1426true:
1427  call void @callee()
1428  store i8 0, ptr %p
1429  br label %done
1430
1431done:
1432  store i8 0, ptr %t
1433  call void @llvm.objc.release(ptr %p)
1434  ret void
1435}
1436
1437; Trivial code motion case: Triangle, with metadata. Do move past
1438; unrelated memory references! And preserve the metadata.
1439
1440; CHECK-LABEL: define void @test28c(
1441; CHECK-NOT: @llvm.objc.
1442; CHECK: true:
1443; CHECK: call ptr @llvm.objc.retain
1444; CHECK: call void @callee()
1445; CHECK: store
1446; CHECK: call void @llvm.objc.release(ptr %p) [[NUW]], !clang.imprecise_release
1447; CHECK: done:
1448; CHECK-NOT: @llvm.objc.
1449; CHECK: {{^}}}
1450define void @test28c(ptr %p, i1 %x, ptr noalias %t) {
1451entry:
1452  %f0 = call ptr @llvm.objc.retain(ptr %p)
1453  br i1 %x, label %true, label %done
1454
1455true:
1456  call void @callee()
1457  store i8 0, ptr %p
1458  br label %done
1459
1460done:
1461  store i8 0, ptr %t
1462  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1463  ret void
1464}
1465
1466; Like test28. but with two releases.
1467
1468; CHECK-LABEL: define void @test29(
1469; CHECK: call ptr @llvm.objc.retain
1470; CHECK: true:
1471; CHECK: call void @callee()
1472; CHECK: store
1473; CHECK: done:
1474; CHECK: call void @llvm.objc.release
1475; CHECK: ohno:
1476; CHECK: call void @llvm.objc.release
1477; CHECK: {{^}}}
1478define void @test29(ptr %p, i1 %x, i1 %y) {
1479entry:
1480  %f0 = call ptr @llvm.objc.retain(ptr %p)
1481  br i1 %x, label %true, label %done
1482
1483true:
1484  call void @callee()
1485  store i8 0, ptr %p
1486  br i1 %y, label %done, label %ohno
1487
1488done:
1489  call void @llvm.objc.release(ptr %p)
1490  ret void
1491
1492ohno:
1493  call void @llvm.objc.release(ptr %p)
1494  ret void
1495}
1496
1497; Basic case with the use and call in a diamond
1498; with an extra release.
1499
1500; CHECK-LABEL: define void @test30(
1501; CHECK: call ptr @llvm.objc.retain
1502; CHECK: true:
1503; CHECK: call void @callee()
1504; CHECK: store
1505; CHECK: false:
1506; CHECK: done:
1507; CHECK: call void @llvm.objc.release
1508; CHECK: ohno:
1509; CHECK: call void @llvm.objc.release
1510; CHECK: {{^}}}
1511define void @test30(ptr %p, i1 %x, i1 %y, i1 %z) {
1512entry:
1513  %f0 = call ptr @llvm.objc.retain(ptr %p)
1514  br i1 %x, label %true, label %false
1515
1516true:
1517  call void @callee()
1518  store i8 0, ptr %p
1519  br i1 %y, label %done, label %ohno
1520
1521false:
1522  br i1 %z, label %done, label %ohno
1523
1524done:
1525  call void @llvm.objc.release(ptr %p)
1526  ret void
1527
1528ohno:
1529  call void @llvm.objc.release(ptr %p)
1530  ret void
1531}
1532
1533; Basic case with a mergeable release.
1534
1535; CHECK-LABEL: define void @test31(
1536; CHECK: call ptr @llvm.objc.retain(ptr %p)
1537; CHECK: call void @callee()
1538; CHECK: store
1539; CHECK: true:
1540; CHECK: call void @llvm.objc.release
1541; CHECK: false:
1542; CHECK: call void @llvm.objc.release
1543; CHECK: ret void
1544; CHECK: {{^}}}
1545define void @test31(ptr %p, i1 %x) {
1546entry:
1547  %f0 = call ptr @llvm.objc.retain(ptr %p)
1548  call void @callee()
1549  store i8 0, ptr %p
1550  br i1 %x, label %true, label %false
1551true:
1552  call void @llvm.objc.release(ptr %p)
1553  ret void
1554false:
1555  call void @llvm.objc.release(ptr %p)
1556  ret void
1557}
1558
1559; Don't consider bitcasts or getelementptrs direct uses.
1560
1561; CHECK-LABEL: define void @test32(
1562; CHECK: call ptr @llvm.objc.retain
1563; CHECK: true:
1564; CHECK: call void @callee()
1565; CHECK: store
1566; CHECK: done:
1567; CHECK: call void @llvm.objc.release
1568; CHECK: {{^}}}
1569define void @test32(ptr %p, i1 %x) {
1570entry:
1571  %f0 = call ptr @llvm.objc.retain(ptr %p)
1572  br i1 %x, label %true, label %done
1573
1574true:
1575  call void @callee()
1576  store i8 0, ptr %p
1577  br label %done
1578
1579done:
1580  call void @llvm.objc.release(ptr %p)
1581  ret void
1582}
1583
1584; Do consider icmps to be direct uses.
1585
1586; CHECK-LABEL: define void @test33(
1587; CHECK: call ptr @llvm.objc.retain
1588; CHECK: true:
1589; CHECK: call void @callee()
1590; CHECK: icmp
1591; CHECK: done:
1592; CHECK: call void @llvm.objc.release
1593; CHECK: {{^}}}
1594define void @test33(ptr %p, i1 %x, ptr %y) {
1595entry:
1596  %f0 = call ptr @llvm.objc.retain(ptr %p)
1597  br i1 %x, label %true, label %done
1598
1599true:
1600  call void @callee()
1601  %v = icmp eq ptr %p, %y
1602  br label %done
1603
1604done:
1605  call void @llvm.objc.release(ptr %p)
1606  ret void
1607}
1608
1609; Delete retain,release if there's just a possible dec and we have imprecise
1610; releases.
1611
1612; CHECK-LABEL: define void @test34a(
1613; CHECK:   call ptr @llvm.objc.retain
1614; CHECK: true:
1615; CHECK: done:
1616; CHECK: call void @llvm.objc.release
1617; CHECK: {{^}}}
1618define void @test34a(ptr %p, i1 %x, ptr %y) {
1619entry:
1620  %f0 = call ptr @llvm.objc.retain(ptr %p)
1621  br i1 %x, label %true, label %done
1622
1623true:
1624  call void @callee()
1625  br label %done
1626
1627done:
1628  call void @llvm.objc.release(ptr %p)
1629  ret void
1630}
1631
1632; CHECK-LABEL: define void @test34b(
1633; CHECK-NOT: @llvm.objc.
1634; CHECK: {{^}}}
1635define void @test34b(ptr %p, i1 %x, ptr %y) {
1636entry:
1637  %f0 = call ptr @llvm.objc.retain(ptr %p)
1638  br i1 %x, label %true, label %done
1639
1640true:
1641  call void @callee()
1642  br label %done
1643
1644done:
1645  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1646  ret void
1647}
1648
1649
1650; Delete retain,release if there's just a use and we do not have a precise
1651; release.
1652
1653; Precise.
1654; CHECK-LABEL: define void @test35a(
1655; CHECK: entry:
1656; CHECK:   call ptr @llvm.objc.retain
1657; CHECK: true:
1658; CHECK: done:
1659; CHECK:   call void @llvm.objc.release
1660; CHECK: {{^}}}
1661define void @test35a(ptr %p, i1 %x, ptr %y) {
1662entry:
1663  %f0 = call ptr @llvm.objc.retain(ptr %p)
1664  br i1 %x, label %true, label %done
1665
1666true:
1667  %v = icmp eq ptr %p, %y
1668  br label %done
1669
1670done:
1671  call void @llvm.objc.release(ptr %p)
1672  ret void
1673}
1674
1675; Imprecise.
1676; CHECK-LABEL: define void @test35b(
1677; CHECK-NOT: @llvm.objc.
1678; CHECK: {{^}}}
1679define void @test35b(ptr %p, i1 %x, ptr %y) {
1680entry:
1681  %f0 = call ptr @llvm.objc.retain(ptr %p)
1682  br i1 %x, label %true, label %done
1683
1684true:
1685  %v = icmp eq ptr %p, %y
1686  br label %done
1687
1688done:
1689  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1690  ret void
1691}
1692
1693; Delete a retain,release if there's no actual use and we have precise release.
1694
1695; CHECK-LABEL: define void @test36a(
1696; CHECK: @llvm.objc.retain
1697; CHECK: call void @callee()
1698; CHECK-NOT: @llvm.objc.
1699; CHECK: call void @callee()
1700; CHECK: @llvm.objc.release
1701; CHECK: {{^}}}
1702define void @test36a(ptr %p) {
1703entry:
1704  call ptr @llvm.objc.retain(ptr %p)
1705  call void @callee()
1706  call void @callee()
1707  call void @llvm.objc.release(ptr %p)
1708  ret void
1709}
1710
1711; Like test36, but with metadata.
1712
1713; CHECK-LABEL: define void @test36b(
1714; CHECK-NOT: @llvm.objc.
1715; CHECK: {{^}}}
1716define void @test36b(ptr %p) {
1717entry:
1718  call ptr @llvm.objc.retain(ptr %p)
1719  call void @callee()
1720  call void @callee()
1721  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1722  ret void
1723}
1724
1725; Be aggressive about analyzing phis to eliminate possible uses.
1726
1727; CHECK-LABEL: define void @test38(
1728; CHECK-NOT: @llvm.objc.
1729; CHECK: {{^}}}
1730define void @test38(ptr %p, i1 %u, i1 %m, ptr %z, ptr %y, ptr %x, ptr %w) {
1731entry:
1732  call ptr @llvm.objc.retain(ptr %p)
1733  br i1 %u, label %true, label %false
1734true:
1735  br i1 %m, label %a, label %b
1736false:
1737  br i1 %m, label %c, label %d
1738a:
1739  br label %e
1740b:
1741  br label %e
1742c:
1743  br label %f
1744d:
1745  br label %f
1746e:
1747  %j = phi ptr [ %z, %a ], [ %y, %b ]
1748  br label %g
1749f:
1750  %k = phi ptr [ %w, %c ], [ %x, %d ]
1751  br label %g
1752g:
1753  %h = phi ptr [ %j, %e ], [ %k, %f ]
1754  call void @use_pointer(ptr %h)
1755  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1756  ret void
1757}
1758
1759; Delete retain,release pairs around loops.
1760
1761; CHECK-LABEL: define void @test39(
1762; CHECK-NOT: @llvm.objc.
1763; CHECK: {{^}}}
1764define void @test39(ptr %p, i1 %arg) {
1765entry:
1766  %0 = call ptr @llvm.objc.retain(ptr %p)
1767  br label %loop
1768
1769loop:                                             ; preds = %loop, %entry
1770  br i1 %arg, label %loop, label %exit
1771
1772exit:                                             ; preds = %loop
1773  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1774  ret void
1775}
1776
1777; Delete retain,release pairs around loops containing uses.
1778
1779; CHECK-LABEL: define void @test39b(
1780; CHECK-NOT: @llvm.objc.
1781; CHECK: {{^}}}
1782define void @test39b(ptr %p, i1 %arg) {
1783entry:
1784  %0 = call ptr @llvm.objc.retain(ptr %p)
1785  br label %loop
1786
1787loop:                                             ; preds = %loop, %entry
1788  store i8 0, ptr %0
1789  br i1 %arg, label %loop, label %exit
1790
1791exit:                                             ; preds = %loop
1792  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1793  ret void
1794}
1795
1796; Delete retain,release pairs around loops containing potential decrements.
1797
1798; CHECK-LABEL: define void @test39c(
1799; CHECK-NOT: @llvm.objc.
1800; CHECK: {{^}}}
1801define void @test39c(ptr %p, i1 %arg) {
1802entry:
1803  %0 = call ptr @llvm.objc.retain(ptr %p)
1804  br label %loop
1805
1806loop:                                             ; preds = %loop, %entry
1807  call void @use_pointer(ptr %0)
1808  br i1 %arg, label %loop, label %exit
1809
1810exit:                                             ; preds = %loop
1811  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1812  ret void
1813}
1814
1815; Delete retain,release pairs around loops even if
1816; the successors are in a different order.
1817
1818; CHECK-LABEL: define void @test40(
1819; CHECK-NOT: @llvm.objc.
1820; CHECK: {{^}}}
1821define void @test40(ptr %p, i1 %arg) {
1822entry:
1823  %0 = call ptr @llvm.objc.retain(ptr %p)
1824  br label %loop
1825
1826loop:                                             ; preds = %loop, %entry
1827  call void @use_pointer(ptr %0)
1828  br i1 %arg, label %exit, label %loop
1829
1830exit:                                             ; preds = %loop
1831  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1832  ret void
1833}
1834
1835; Do the known-incremented retain+release elimination even if the pointer
1836; is also autoreleased.
1837
1838; CHECK-LABEL: define void @test42(
1839; CHECK-NEXT: entry:
1840; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
1841; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
1842; CHECK-NEXT: call void @use_pointer(ptr %p)
1843; CHECK-NEXT: call void @use_pointer(ptr %p)
1844; CHECK-NEXT: call void @use_pointer(ptr %p)
1845; CHECK-NEXT: call void @use_pointer(ptr %p)
1846; CHECK-NEXT: call void @llvm.objc.release(ptr %p)
1847; CHECK-NEXT: ret void
1848; CHECK-NEXT: }
1849define void @test42(ptr %p) {
1850entry:
1851  call ptr @llvm.objc.retain(ptr %p)
1852  call ptr @llvm.objc.autorelease(ptr %p)
1853  call ptr @llvm.objc.retain(ptr %p)
1854  call void @use_pointer(ptr %p)
1855  call void @use_pointer(ptr %p)
1856  call void @llvm.objc.release(ptr %p)
1857  call void @use_pointer(ptr %p)
1858  call void @use_pointer(ptr %p)
1859  call void @llvm.objc.release(ptr %p)
1860  ret void
1861}
1862
1863; Don't the known-incremented retain+release elimination if the pointer is
1864; autoreleased and there's an autoreleasePoolPop.
1865
1866; CHECK-LABEL: define void @test43(
1867; CHECK-NEXT: entry:
1868; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
1869; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
1870; CHECK-NEXT: call ptr @llvm.objc.retain
1871; CHECK-NEXT: call void @use_pointer(ptr %p)
1872; CHECK-NEXT: call void @use_pointer(ptr %p)
1873; CHECK-NEXT: call void @llvm.objc.autoreleasePoolPop(ptr undef)
1874; CHECK-NEXT: call void @llvm.objc.release
1875; CHECK-NEXT: ret void
1876; CHECK-NEXT: }
1877define void @test43(ptr %p) {
1878entry:
1879  call ptr @llvm.objc.retain(ptr %p)
1880  call ptr @llvm.objc.autorelease(ptr %p)
1881  call ptr @llvm.objc.retain(ptr %p)
1882  call void @use_pointer(ptr %p)
1883  call void @use_pointer(ptr %p)
1884  call void @llvm.objc.autoreleasePoolPop(ptr undef)
1885  call void @llvm.objc.release(ptr %p)
1886  ret void
1887}
1888
1889; Do the known-incremented retain+release elimination if the pointer is
1890; autoreleased and there's an autoreleasePoolPush.
1891
1892; CHECK-LABEL: define void @test43b(
1893; CHECK-NEXT: entry:
1894; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
1895; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
1896; CHECK-NEXT: call void @use_pointer(ptr %p)
1897; CHECK-NEXT: call void @use_pointer(ptr %p)
1898; CHECK-NEXT: call ptr @llvm.objc.autoreleasePoolPush()
1899; CHECK-NEXT: call void @use_pointer(ptr %p)
1900; CHECK-NEXT: call void @llvm.objc.release
1901; CHECK-NEXT: ret void
1902; CHECK-NEXT: }
1903define void @test43b(ptr %p) {
1904entry:
1905  call ptr @llvm.objc.retain(ptr %p)
1906  call ptr @llvm.objc.autorelease(ptr %p)
1907  call ptr @llvm.objc.retain(ptr %p)
1908  call void @use_pointer(ptr %p)
1909  call void @use_pointer(ptr %p)
1910  call ptr @llvm.objc.autoreleasePoolPush()
1911  call void @llvm.objc.release(ptr %p)
1912  call void @use_pointer(ptr %p)
1913  call void @llvm.objc.release(ptr %p)
1914  ret void
1915}
1916
1917; Do retain+release elimination for non-provenance pointers.
1918
1919; CHECK-LABEL: define void @test44(
1920; CHECK-NOT: llvm.objc.
1921; CHECK: {{^}}}
1922define void @test44(ptr %pp) {
1923  %p = load ptr, ptr %pp
1924  %q = call ptr @llvm.objc.retain(ptr %p)
1925  call void @llvm.objc.release(ptr %q)
1926  ret void
1927}
1928
1929; Don't delete retain+release with an unknown-provenance
1930; may-alias llvm.objc.release between them.
1931
1932; CHECK-LABEL: define void @test45(
1933; CHECK: call ptr @llvm.objc.retain(ptr %p)
1934; CHECK: call void @llvm.objc.release(ptr %q)
1935; CHECK: call void @use_pointer(ptr %p)
1936; CHECK: call void @llvm.objc.release(ptr %p)
1937; CHECK: {{^}}}
1938define void @test45(ptr %pp, ptr %qq) {
1939  %p = load ptr, ptr %pp
1940  %q = load ptr, ptr %qq
1941  call ptr @llvm.objc.retain(ptr %p)
1942  call void @llvm.objc.release(ptr %q)
1943  call void @use_pointer(ptr %p)
1944  call void @llvm.objc.release(ptr %p)
1945  ret void
1946}
1947
1948; Don't delete retain and autorelease here.
1949
1950; CHECK-LABEL: define void @test46(
1951; CHECK: tail call ptr @llvm.objc.retain(ptr %p) [[NUW]]
1952; CHECK: true:
1953; CHECK: call ptr @llvm.objc.autorelease(ptr %p) [[NUW]]
1954; CHECK: {{^}}}
1955define void @test46(ptr %p, i1 %a) {
1956entry:
1957  call ptr @llvm.objc.retain(ptr %p)
1958  br i1 %a, label %true, label %false
1959
1960true:
1961  call ptr @llvm.objc.autorelease(ptr %p)
1962  call void @use_pointer(ptr %p)
1963  ret void
1964
1965false:
1966  ret void
1967}
1968
1969; Delete no-op cast calls.
1970
1971; CHECK-LABEL: define ptr @test47(
1972; CHECK-NOT: call
1973; CHECK: ret ptr %p
1974; CHECK: {{^}}}
1975define ptr @test47(ptr %p) nounwind {
1976  %x = call ptr @llvm.objc.retainedObject(ptr %p)
1977  ret ptr %x
1978}
1979
1980; Delete no-op cast calls.
1981
1982; CHECK-LABEL: define ptr @test48(
1983; CHECK-NOT: call
1984; CHECK: ret ptr %p
1985; CHECK: {{^}}}
1986define ptr @test48(ptr %p) nounwind {
1987  %x = call ptr @llvm.objc.unretainedObject(ptr %p)
1988  ret ptr %x
1989}
1990
1991; Delete no-op cast calls.
1992
1993; CHECK-LABEL: define ptr @test49(
1994; CHECK-NOT: call
1995; CHECK: ret ptr %p
1996; CHECK: {{^}}}
1997define ptr @test49(ptr %p) nounwind {
1998  %x = call ptr @llvm.objc.unretainedPointer(ptr %p)
1999  ret ptr %x
2000}
2001
2002; Do delete retain+release with intervening stores of the address value if we
2003; have imprecise release attached to llvm.objc.release.
2004
2005; CHECK-LABEL:      define void @test50a(
2006; CHECK-NEXT:   call ptr @llvm.objc.retain
2007; CHECK-NEXT:   call void @callee
2008; CHECK-NEXT:   store
2009; CHECK-NEXT:   call void @llvm.objc.release
2010; CHECK-NEXT:   ret void
2011; CHECK-NEXT: }
2012define void @test50a(ptr %p, ptr %pp) {
2013  call ptr @llvm.objc.retain(ptr %p)
2014  call void @callee()
2015  store ptr %p, ptr %pp
2016  call void @llvm.objc.release(ptr %p)
2017  ret void
2018}
2019
2020; CHECK-LABEL: define void @test50b(
2021; CHECK-NOT: @llvm.objc.
2022; CHECK: {{^}}}
2023define void @test50b(ptr %p, ptr %pp) {
2024  call ptr @llvm.objc.retain(ptr %p)
2025  call void @callee()
2026  store ptr %p, ptr %pp
2027  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2028  ret void
2029}
2030
2031
2032; Don't delete retain+release with intervening stores through the
2033; address value.
2034
2035; CHECK-LABEL: define void @test51a(
2036; CHECK: call ptr @llvm.objc.retain(ptr %p)
2037; CHECK: call void @llvm.objc.release(ptr %p)
2038; CHECK: ret void
2039; CHECK: {{^}}}
2040define void @test51a(ptr %p) {
2041  call ptr @llvm.objc.retain(ptr %p)
2042  call void @callee()
2043  store i8 0, ptr %p
2044  call void @llvm.objc.release(ptr %p)
2045  ret void
2046}
2047
2048; CHECK-LABEL: define void @test51b(
2049; CHECK: call ptr @llvm.objc.retain(ptr %p)
2050; CHECK: call void @llvm.objc.release(ptr %p)
2051; CHECK: ret void
2052; CHECK: {{^}}}
2053define void @test51b(ptr %p) {
2054  call ptr @llvm.objc.retain(ptr %p)
2055  call void @callee()
2056  store i8 0, ptr %p
2057  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2058  ret void
2059}
2060
2061; Don't delete retain+release with intervening use of a pointer of
2062; unknown provenance.
2063
2064; CHECK-LABEL: define void @test52a(
2065; CHECK: call ptr @llvm.objc.retain
2066; CHECK: call void @callee()
2067; CHECK: call void @use_pointer(ptr %z)
2068; CHECK: call void @llvm.objc.release
2069; CHECK: ret void
2070; CHECK: {{^}}}
2071define void @test52a(ptr %zz, ptr %pp) {
2072  %p = load ptr, ptr %pp
2073  %1 = call ptr @llvm.objc.retain(ptr %p)
2074  call void @callee()
2075  %z = load ptr, ptr %zz
2076  call void @use_pointer(ptr %z)
2077  call void @llvm.objc.release(ptr %p)
2078  ret void
2079}
2080
2081; CHECK-LABEL: define void @test52b(
2082; CHECK: call ptr @llvm.objc.retain
2083; CHECK: call void @callee()
2084; CHECK: call void @use_pointer(ptr %z)
2085; CHECK: call void @llvm.objc.release
2086; CHECK: ret void
2087; CHECK: {{^}}}
2088define void @test52b(ptr %zz, ptr %pp) {
2089  %p = load ptr, ptr %pp
2090  %1 = call ptr @llvm.objc.retain(ptr %p)
2091  call void @callee()
2092  %z = load ptr, ptr %zz
2093  call void @use_pointer(ptr %z)
2094  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2095  ret void
2096}
2097
2098; Like test52, but the pointer has function type, so it's assumed to
2099; be not reference counted.
2100; Oops. That's wrong. Clang sometimes uses function types gratuitously.
2101; See rdar://10551239.
2102
2103; CHECK-LABEL: define void @test53(
2104; CHECK: @llvm.objc.
2105; CHECK: {{^}}}
2106define void @test53(ptr %zz, ptr %pp) {
2107  %p = load ptr, ptr %pp
2108  %1 = call ptr @llvm.objc.retain(ptr %p)
2109  call void @callee()
2110  %z = load ptr, ptr %zz
2111  call void @callee_fnptr(ptr %z)
2112  call void @llvm.objc.release(ptr %p)
2113  ret void
2114}
2115
2116; Convert autorelease to release if the value is unused.
2117
2118; CHECK-LABEL: define void @test54(
2119; CHECK: call ptr @returner()
2120; CHECK-NEXT: call void @llvm.objc.release(ptr %t) [[NUW]], !clang.imprecise_release ![[RELEASE]]
2121; CHECK-NEXT: ret void
2122; CHECK: {{^}}}
2123define void @test54() {
2124  %t = call ptr @returner()
2125  call ptr @llvm.objc.autorelease(ptr %t)
2126  ret void
2127}
2128
2129; Nested retain+release pairs. Delete them both.
2130
2131; CHECK-LABEL: define void @test55(
2132; CHECK-NOT: @objc
2133; CHECK: {{^}}}
2134define void @test55(ptr %x) {
2135entry:
2136  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
2137  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
2138  call void @llvm.objc.release(ptr %x) nounwind
2139  call void @llvm.objc.release(ptr %x) nounwind
2140  ret void
2141}
2142
2143; Nested retain+release pairs where the inner pair depends
2144; on the outer pair to be removed, and then the outer pair
2145; can be partially eliminated. Plus an extra outer pair to
2146; eliminate, for fun.
2147
2148; CHECK-LABEL: define void @test56(
2149; CHECK-NOT: @objc
2150; CHECK: if.then:
2151; CHECK-NEXT: %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2152; CHECK-NEXT: tail call void @use_pointer(ptr %x)
2153; CHECK-NEXT: tail call void @use_pointer(ptr %x)
2154; CHECK-NEXT: tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE]]
2155; CHECK-NEXT: br label %if.end
2156; CHECK-NOT: @objc
2157; CHECK: {{^}}}
2158define void @test56(ptr %x, i32 %n) {
2159entry:
2160  %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
2161  %1 = tail call ptr @llvm.objc.retain(ptr %0) nounwind
2162  %tobool = icmp eq i32 %n, 0
2163  br i1 %tobool, label %if.end, label %if.then
2164
2165if.then:                                          ; preds = %entry
2166  %2 = tail call ptr @llvm.objc.retain(ptr %1) nounwind
2167  tail call void @use_pointer(ptr %2)
2168  tail call void @use_pointer(ptr %2)
2169  tail call void @llvm.objc.release(ptr %2) nounwind, !clang.imprecise_release !0
2170  br label %if.end
2171
2172if.end:                                           ; preds = %entry, %if.then
2173  tail call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0
2174  tail call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0
2175  ret void
2176}
2177
2178; When there are adjacent retain+release pairs, the first one is known
2179; unnecessary because the presence of the second one means that the first one
2180; won't be deleting the object.
2181
2182; CHECK-LABEL:      define void @test57(
2183; CHECK-NEXT: entry:
2184; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2185; CHECK-NEXT:   call void @use_pointer(ptr %x)
2186; CHECK-NEXT:   call void @use_pointer(ptr %x)
2187; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2188; CHECK-NEXT:   call void @use_pointer(ptr %x)
2189; CHECK-NEXT:   call void @use_pointer(ptr %x)
2190; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]
2191; CHECK-NEXT:   ret void
2192; CHECK-NEXT: }
2193define void @test57(ptr %x) nounwind {
2194entry:
2195  call ptr @llvm.objc.retain(ptr %x) nounwind
2196  call ptr @llvm.objc.retain(ptr %x) nounwind
2197  call void @use_pointer(ptr %x)
2198  call void @use_pointer(ptr %x)
2199  call void @llvm.objc.release(ptr %x) nounwind
2200  call ptr @llvm.objc.retain(ptr %x) nounwind
2201  call void @use_pointer(ptr %x)
2202  call void @use_pointer(ptr %x)
2203  call void @llvm.objc.release(ptr %x) nounwind
2204  ret void
2205}
2206
2207; An adjacent retain+release pair is sufficient even if it will be
2208; removed itself.
2209
2210; CHECK-LABEL:      define void @test58(
2211; CHECK-NEXT: entry:
2212; CHECK-NEXT:   @llvm.objc.retain
2213; CHECK-NEXT:   call void @use_pointer(ptr %x)
2214; CHECK-NEXT:   call void @use_pointer(ptr %x)
2215; CHECK-NEXT:   ret void
2216; CHECK-NEXT: }
2217define void @test58(ptr %x) nounwind {
2218entry:
2219  call ptr @llvm.objc.retain(ptr %x) nounwind
2220  call ptr @llvm.objc.retain(ptr %x) nounwind
2221  call void @use_pointer(ptr %x)
2222  call void @use_pointer(ptr %x)
2223  call void @llvm.objc.release(ptr %x) nounwind
2224  call ptr @llvm.objc.retain(ptr %x) nounwind
2225  call void @llvm.objc.release(ptr %x) nounwind
2226  ret void
2227}
2228
2229; Don't delete the second retain+release pair in an adjacent set.
2230
2231; CHECK-LABEL:      define void @test59(
2232; CHECK-NEXT: entry:
2233; CHECK-NEXT:   %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2234; CHECK-NEXT:   call void @use_pointer(ptr %x)
2235; CHECK-NEXT:   call void @use_pointer(ptr %x)
2236; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]
2237; CHECK-NEXT:   ret void
2238; CHECK-NEXT: }
2239define void @test59(ptr %x) nounwind {
2240entry:
2241  %a = call ptr @llvm.objc.retain(ptr %x) nounwind
2242  call void @llvm.objc.release(ptr %x) nounwind
2243  %b = call ptr @llvm.objc.retain(ptr %x) nounwind
2244  call void @use_pointer(ptr %x)
2245  call void @use_pointer(ptr %x)
2246  call void @llvm.objc.release(ptr %x) nounwind
2247  ret void
2248}
2249
2250; Constant pointers to objects don't need reference counting.
2251
2252@constptr = external constant ptr
2253@something = external global ptr
2254
2255; We have a precise lifetime retain/release here. We can not remove them since
2256; @something is not constant.
2257
2258; CHECK-LABEL: define void @test60a(
2259; CHECK: call ptr @llvm.objc.retain
2260; CHECK: call void @llvm.objc.release
2261; CHECK: {{^}}}
2262define void @test60a() {
2263  %t = load ptr, ptr @constptr
2264  %s = load ptr, ptr @something
2265  call ptr @llvm.objc.retain(ptr %s)
2266  call void @callee()
2267  call void @use_pointer(ptr %t)
2268  call void @llvm.objc.release(ptr %s)
2269  ret void
2270}
2271
2272; CHECK-LABEL: define void @test60b(
2273; CHECK: call ptr @llvm.objc.retain
2274; CHECK-NOT: call ptr @llvm.objc.retain
2275; CHECK-NOT: call ptr @llvm.objc.release
2276; CHECK: {{^}}}
2277define void @test60b() {
2278  %t = load ptr, ptr @constptr
2279  %s = load ptr, ptr @something
2280  call ptr @llvm.objc.retain(ptr %t)
2281  call ptr @llvm.objc.retain(ptr %t)
2282  call void @callee()
2283  call void @use_pointer(ptr %s)
2284  call void @llvm.objc.release(ptr %t)
2285  ret void
2286}
2287
2288; CHECK-LABEL: define void @test60c(
2289; CHECK-NOT: @llvm.objc.
2290; CHECK: {{^}}}
2291define void @test60c() {
2292  %t = load ptr, ptr @constptr
2293  %s = load ptr, ptr @something
2294  call ptr @llvm.objc.retain(ptr %t)
2295  call void @callee()
2296  call void @use_pointer(ptr %s)
2297  call void @llvm.objc.release(ptr %t), !clang.imprecise_release !0
2298  ret void
2299}
2300
2301; CHECK-LABEL: define void @test60d(
2302; CHECK-NOT: @llvm.objc.
2303; CHECK: {{^}}}
2304define void @test60d() {
2305  %t = load ptr, ptr @constptr
2306  %s = load ptr, ptr @something
2307  call ptr @llvm.objc.retain(ptr %t)
2308  call void @callee()
2309  call void @use_pointer(ptr %s)
2310  call void @llvm.objc.release(ptr %t)
2311  ret void
2312}
2313
2314; CHECK-LABEL: define void @test60e(
2315; CHECK-NOT: @llvm.objc.
2316; CHECK: {{^}}}
2317define void @test60e() {
2318  %t = load ptr, ptr @constptr
2319  %s = load ptr, ptr @something
2320  call ptr @llvm.objc.retain(ptr %t)
2321  call void @callee()
2322  call void @use_pointer(ptr %s)
2323  call void @llvm.objc.release(ptr %t), !clang.imprecise_release !0
2324  ret void
2325}
2326
2327; Constant pointers to objects don't need to be considered related to other
2328; pointers.
2329
2330; CHECK-LABEL: define void @test61(
2331; CHECK-NOT: @llvm.objc.
2332; CHECK: {{^}}}
2333define void @test61() {
2334  %t = load ptr, ptr @constptr
2335  call ptr @llvm.objc.retain(ptr %t)
2336  call void @callee()
2337  call void @use_pointer(ptr %t)
2338  call void @llvm.objc.release(ptr %t)
2339  ret void
2340}
2341
2342; Delete a retain matched by releases when one is inside the loop and the
2343; other is outside the loop.
2344
2345; CHECK-LABEL: define void @test62(
2346; CHECK-NOT: @llvm.objc.
2347; CHECK: {{^}}}
2348define void @test62(ptr %x, ptr %p) nounwind {
2349entry:
2350  br label %loop
2351
2352loop:
2353  call ptr @llvm.objc.retain(ptr %x)
2354  %q = load i1, ptr %p
2355  br i1 %q, label %loop.more, label %exit
2356
2357loop.more:
2358  call void @llvm.objc.release(ptr %x)
2359  br label %loop
2360
2361exit:
2362  call void @llvm.objc.release(ptr %x)
2363  ret void
2364}
2365
2366; Like test62 but with no release in exit.
2367; Don't delete anything!
2368
2369; CHECK-LABEL: define void @test63(
2370; CHECK: loop:
2371; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)
2372; CHECK: loop.more:
2373; CHECK:   call void @llvm.objc.release(ptr %x)
2374; CHECK: {{^}}}
2375define void @test63(ptr %x, ptr %p) nounwind {
2376entry:
2377  br label %loop
2378
2379loop:
2380  call ptr @llvm.objc.retain(ptr %x)
2381  %q = load i1, ptr %p
2382  br i1 %q, label %loop.more, label %exit
2383
2384loop.more:
2385  call void @llvm.objc.release(ptr %x)
2386  br label %loop
2387
2388exit:
2389  ret void
2390}
2391
2392; Like test62 but with no release in loop.more.
2393; Don't delete anything!
2394
2395; CHECK-LABEL: define void @test64(
2396; CHECK: loop:
2397; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)
2398; CHECK: exit:
2399; CHECK:   call void @llvm.objc.release(ptr %x)
2400; CHECK: {{^}}}
2401define void @test64(ptr %x, ptr %p) nounwind {
2402entry:
2403  br label %loop
2404
2405loop:
2406  call ptr @llvm.objc.retain(ptr %x)
2407  %q = load i1, ptr %p
2408  br i1 %q, label %loop.more, label %exit
2409
2410loop.more:
2411  br label %loop
2412
2413exit:
2414  call void @llvm.objc.release(ptr %x)
2415  ret void
2416}
2417
2418; Move an autorelease past a phi with a null.
2419
2420; CHECK-LABEL: define ptr @test65(
2421; CHECK: if.then:
2422; CHECK:   call ptr @llvm.objc.autorelease(
2423; CHECK: return:
2424; CHECK-NOT: @llvm.objc.autorelease
2425; CHECK: {{^}}}
2426define ptr @test65(i1 %x) {
2427entry:
2428  br i1 %x, label %return, label %if.then
2429
2430if.then:                                          ; preds = %entry
2431  %c = call ptr @returner()
2432  %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind
2433  br label %return
2434
2435return:                                           ; preds = %if.then, %entry
2436  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2437  %q = call ptr @llvm.objc.autorelease(ptr %retval) nounwind
2438  ret ptr %retval
2439}
2440
2441; Don't move an autorelease past an autorelease pool boundary.
2442
2443; CHECK-LABEL: define ptr @test65b(
2444; CHECK: if.then:
2445; CHECK-NOT: @llvm.objc.autorelease
2446; CHECK: return:
2447; CHECK:   call ptr @llvm.objc.autorelease(
2448; CHECK: {{^}}}
2449define ptr @test65b(i1 %x) {
2450entry:
2451  %t = call ptr @llvm.objc.autoreleasePoolPush()
2452  br i1 %x, label %return, label %if.then
2453
2454if.then:                                          ; preds = %entry
2455  %c = call ptr @returner()
2456  %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind
2457  br label %return
2458
2459return:                                           ; preds = %if.then, %entry
2460  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2461  call void @llvm.objc.autoreleasePoolPop(ptr %t)
2462  %q = call ptr @llvm.objc.autorelease(ptr %retval) nounwind
2463  ret ptr %retval
2464}
2465
2466; Don't move an autoreleaseReuturnValue, which would break
2467; the RV optimization.
2468
2469; CHECK-LABEL: define ptr @test65c(
2470; CHECK: if.then:
2471; CHECK-NOT: @llvm.objc.autorelease
2472; CHECK: return:
2473; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(
2474; CHECK: {{^}}}
2475define ptr @test65c(i1 %x) {
2476entry:
2477  br i1 %x, label %return, label %if.then
2478
2479if.then:                                          ; preds = %entry
2480  %c = call ptr @returner()
2481  %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind
2482  br label %return
2483
2484return:                                           ; preds = %if.then, %entry
2485  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2486  %q = call ptr @llvm.objc.autoreleaseReturnValue(ptr %retval) nounwind
2487  ret ptr %retval
2488}
2489
2490; CHECK-LABEL: define ptr @test65d(
2491; CHECK: if.then:
2492; CHECK-NOT: @llvm.objc.autorelease
2493; CHECK: return:
2494; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(
2495; CHECK: {{^}}}
2496define ptr @test65d(i1 %x) {
2497entry:
2498  br i1 %x, label %return, label %if.then
2499
2500if.then:                                          ; preds = %entry
2501  %c = call ptr @returner()
2502  %s = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr %c) nounwind
2503  br label %return
2504
2505return:                                           ; preds = %if.then, %entry
2506  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2507  %q = call ptr @llvm.objc.autoreleaseReturnValue(ptr %retval) nounwind
2508  ret ptr %retval
2509}
2510
2511; An llvm.objc.retain can serve as a may-use for a different pointer.
2512; rdar://11931823
2513
2514; CHECK-LABEL: define void @test66a(
2515; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2516; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2517; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2518; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2519; CHECK: {{^}}}
2520define void @test66a(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2521entry:
2522  br i1 %tobool, label %cond.true, label %cond.end
2523
2524cond.true:
2525  br label %cond.end
2526
2527cond.end:                                         ; preds = %cond.true, %entry
2528  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2529  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2530  tail call void @llvm.objc.release(ptr %call) nounwind
2531  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2532  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind
2533  tail call void @llvm.objc.release(ptr %cond) nounwind
2534  ret void
2535}
2536
2537; CHECK-LABEL: define void @test66b(
2538; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2539; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2540; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2541; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2542; CHECK: {{^}}}
2543define void @test66b(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2544entry:
2545  br i1 %tobool, label %cond.true, label %cond.end
2546
2547cond.true:
2548  br label %cond.end
2549
2550cond.end:                                         ; preds = %cond.true, %entry
2551  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2552  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2553  tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0
2554  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2555  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind
2556  tail call void @llvm.objc.release(ptr %cond) nounwind
2557  ret void
2558}
2559
2560; CHECK-LABEL: define void @test66c(
2561; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2562; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2563; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2564; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2565; CHECK: {{^}}}
2566define void @test66c(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2567entry:
2568  br i1 %tobool, label %cond.true, label %cond.end
2569
2570cond.true:
2571  br label %cond.end
2572
2573cond.end:                                         ; preds = %cond.true, %entry
2574  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2575  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2576  tail call void @llvm.objc.release(ptr %call) nounwind
2577  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2578  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind, !clang.imprecise_release !0
2579  tail call void @llvm.objc.release(ptr %cond) nounwind
2580  ret void
2581}
2582
2583; CHECK-LABEL: define void @test66d(
2584; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2585; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2586; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2587; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2588; CHECK: {{^}}}
2589define void @test66d(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2590entry:
2591  br i1 %tobool, label %cond.true, label %cond.end
2592
2593cond.true:
2594  br label %cond.end
2595
2596cond.end:                                         ; preds = %cond.true, %entry
2597  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2598  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2599  tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0
2600  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2601  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind
2602  tail call void @llvm.objc.release(ptr %cond) nounwind, !clang.imprecise_release !0
2603  ret void
2604}
2605
2606; A few real-world testcases.
2607
2608@.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00"
2609@"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8
2610declare i32 @printf(ptr captures(none), ...) nounwind
2611declare i32 @puts(ptr captures(none)) nounwind
2612@str = internal constant [16 x i8] c"-[ Top0 _getX ]\00"
2613
2614; FIXME: Should be able to eliminate the retain and release
2615; CHECK-LABEL: define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr captures(none) %_cmd)
2616; CHECK: tail call ptr @llvm.objc.retain(ptr %self)
2617; CHECK-NEXT: %call = tail call i32 (ptr, ...) @printf(
2618; CHECK: tail call void @llvm.objc.release(ptr %self)
2619; CHECK: {{^}}}
2620define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr captures(none) %_cmd) nounwind {
2621invoke.cont:
2622  %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind
2623  tail call void @llvm.dbg.value(metadata ptr %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)
2624  tail call void @llvm.dbg.value(metadata ptr %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)
2625  %ivar = load i64, ptr @"OBJC_IVAR_$_A.myZ", align 8
2626  %add.ptr = getelementptr i8, ptr %self, i64 %ivar
2627  %tmp2 = load float, ptr %add.ptr, align 4
2628  %conv = fpext float %tmp2 to double
2629  %add.ptr.sum = add i64 %ivar, 4
2630  %tmp6 = getelementptr inbounds i8, ptr %self, i64 %add.ptr.sum
2631  %tmp7 = load float, ptr %tmp6, align 4
2632  %conv8 = fpext float %tmp7 to double
2633  %add.ptr.sum36 = add i64 %ivar, 8
2634  %tmp12 = getelementptr inbounds i8, ptr %self, i64 %add.ptr.sum36
2635  %tmp13 = load float, ptr %tmp12, align 4
2636  %conv14 = fpext float %tmp13 to double
2637  %tmp12.sum = add i64 %ivar, 12
2638  %arrayidx19 = getelementptr inbounds i8, ptr %self, i64 %tmp12.sum
2639  %tmp20 = load float, ptr %arrayidx19, align 4
2640  %conv21 = fpext float %tmp20 to double
2641  %call = tail call i32 (ptr, ...) @printf(ptr @.str4, double %conv, double %conv8, double %conv14, double %conv21)
2642  %ivar23 = load i64, ptr @"OBJC_IVAR_$_A.myZ", align 8
2643  %add.ptr24 = getelementptr i8, ptr %self, i64 %ivar23
2644  %srcval = load i128, ptr %add.ptr24, align 4
2645  tail call void @llvm.objc.release(ptr %self) nounwind
2646  %tmp29 = trunc i128 %srcval to i64
2647  %tmp30 = bitcast i64 %tmp29 to <2 x float>
2648  %tmp31 = insertvalue { <2 x float>, <2 x float> } undef, <2 x float> %tmp30, 0
2649  %tmp32 = lshr i128 %srcval, 64
2650  %tmp33 = trunc i128 %tmp32 to i64
2651  %tmp34 = bitcast i64 %tmp33 to <2 x float>
2652  %tmp35 = insertvalue { <2 x float>, <2 x float> } %tmp31, <2 x float> %tmp34, 1
2653  ret { <2 x float>, <2 x float> } %tmp35
2654}
2655
2656; FIXME: Should be able to eliminate the retain and release
2657; CHECK-LABEL: @"\01-[Top0 _getX]"(ptr %self, ptr captures(none) %_cmd)
2658; CHECK: tail call ptr @llvm.objc.retain(ptr %self)
2659; CHECK: %puts = tail call i32 @puts
2660; CHECK: tail call void @llvm.objc.release(ptr %self)
2661define i32 @"\01-[Top0 _getX]"(ptr %self, ptr captures(none) %_cmd) nounwind {
2662invoke.cont:
2663  %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind
2664  %puts = tail call i32 @puts(ptr @str)
2665  tail call void @llvm.objc.release(ptr %self) nounwind
2666  ret i32 0
2667}
2668
2669@"\01L_OBJC_METH_VAR_NAME_" = internal global [5 x i8] c"frob\00", section "__TEXT,__cstring,cstring_literals", align 1@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global ptr @"\01L_OBJC_METH_VAR_NAME_", section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2670@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
2671@llvm.used = appending global [3 x ptr] [ptr @"\01L_OBJC_METH_VAR_NAME_", ptr @"\01L_OBJC_SELECTOR_REFERENCES_", ptr @"\01L_OBJC_IMAGE_INFO"], section "llvm.metadata"
2672
2673; A simple loop. Eliminate the retain and release inside of it!
2674
2675; CHECK: define void @loop(ptr %x, i64 %n) {
2676; CHECK: for.body:
2677; CHECK-NOT: @llvm.objc.
2678; CHECK: @objc_msgSend
2679; CHECK-NOT: @llvm.objc.
2680; CHECK: for.end:
2681; CHECK: {{^}}}
2682define void @loop(ptr %x, i64 %n) {
2683entry:
2684  %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
2685  %cmp9 = icmp sgt i64 %n, 0
2686  br i1 %cmp9, label %for.body, label %for.end
2687
2688for.body:                                         ; preds = %entry, %for.body
2689  %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
2690  %1 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
2691  %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
2692  %call = tail call ptr (ptr, ptr, ...) @objc_msgSend(ptr %1, ptr %tmp5)
2693  tail call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0
2694  %inc = add nsw i64 %i.010, 1
2695  %exitcond = icmp eq i64 %inc, %n
2696  br i1 %exitcond, label %for.end, label %for.body
2697
2698for.end:                                          ; preds = %for.body, %entry
2699  tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
2700  ret void
2701}
2702
2703; ObjCARCOpt can delete the retain,release on self.
2704
2705; CHECK: define void @TextEditTest(ptr %self, ptr %pboard) {
2706; CHECK-NOT: call ptr @llvm.objc.retain(ptr %tmp7)
2707; CHECK: {{^}}}
2708
2709%0 = type { ptr, ptr }
2710%1 = type opaque
2711%2 = type opaque
2712%3 = type opaque
2713%4 = type opaque
2714%5 = type opaque
2715%struct.NSConstantString = type { ptr, i32, ptr, i64 }
2716%struct._NSRange = type { i64, i64 }
2717%struct.__CFString = type opaque
2718%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
2719%struct._class_ro_t = type { i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr }
2720%struct._class_t = type { ptr, ptr, ptr, ptr, ptr }
2721%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }
2722%struct._ivar_t = type { ptr, ptr, ptr, i32, i32 }
2723%struct._message_ref_t = type { ptr, ptr }
2724%struct._objc_cache = type opaque
2725%struct._objc_method = type { ptr, ptr, ptr }
2726%struct._objc_protocol_list = type { i64, [0 x ptr] }
2727%struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] }
2728%struct._protocol_t = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, i32 }
2729
2730@"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2731@kUTTypePlainText = external constant ptr
2732@"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2733@"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2734@"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2735@"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2736@"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2737@"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2738@"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2739@"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2740@"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2741@"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2742@"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2743@"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2744@"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2745@"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2746@_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring"
2747@"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2748@"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2749@"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16
2750@"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2751@NSCocoaErrorDomain = external constant ptr
2752@"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2753@NSFilePathErrorKey = external constant ptr
2754@"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2755@"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2756@"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2757@"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2758@"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2759
2760declare ptr @truncatedString(ptr, i64)
2761define void @TextEditTest(ptr %self, ptr %pboard) {
2762entry:
2763  %err = alloca ptr, align 8
2764  %tmp8 = call ptr @llvm.objc.retain(ptr %self) nounwind
2765  store ptr null, ptr %err, align 8
2766  %tmp1 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8
2767  %tmp2 = load ptr, ptr @kUTTypePlainText, align 8
2768  %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8
2769  %call5 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp1, ptr %tmp3, ptr %tmp2)
2770  %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8
2771  %call76 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %pboard, ptr %tmp5, ptr %call5)
2772  %tmp9 = call ptr @llvm.objc.retain(ptr %call76) nounwind
2773  %tobool = icmp eq ptr %tmp9, null
2774  br i1 %tobool, label %end, label %land.lhs.true
2775
2776land.lhs.true:                                    ; preds = %entry
2777  %tmp11 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8
2778  %call137 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %pboard, ptr %tmp11, ptr %tmp9)
2779  %tmp10 = call ptr @llvm.objc.retain(ptr %call137) nounwind
2780  call void @llvm.objc.release(ptr null) nounwind
2781  %tmp12 = call ptr @llvm.objc.retain(ptr %call137) nounwind
2782  call void @llvm.objc.release(ptr null) nounwind
2783  %tobool16 = icmp eq ptr %call137, null
2784  br i1 %tobool16, label %end, label %if.then
2785
2786if.then:                                          ; preds = %land.lhs.true
2787  %tmp19 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
2788  %call21 = call signext i8 @objc_msgSend(ptr %call137, ptr %tmp19)
2789  %tobool22 = icmp eq i8 %call21, 0
2790  br i1 %tobool22, label %if.then44, label %land.lhs.true23
2791
2792land.lhs.true23:                                  ; preds = %if.then
2793  %tmp24 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
2794  %tmp26 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
2795  %call2822 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp24, ptr %tmp26, ptr %call137)
2796  %tmp14 = call ptr @llvm.objc.retain(ptr %call2822) nounwind
2797  call void @llvm.objc.release(ptr null) nounwind
2798  %tobool30 = icmp eq ptr %call2822, null
2799  br i1 %tobool30, label %if.then44, label %if.end
2800
2801if.end:                                           ; preds = %land.lhs.true23
2802  %tmp32 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
2803  %tmp33 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
2804  %call35 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp32, ptr %tmp33)
2805  %tmp37 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
2806  %call3923 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call35, ptr %tmp37, ptr %call2822, i32 signext 1, ptr %err)
2807  %cmp = icmp eq ptr %call3923, null
2808  br i1 %cmp, label %if.then44, label %end
2809
2810if.then44:                                        ; preds = %if.end, %land.lhs.true23, %if.then
2811  %url.025 = phi ptr [ %call2822, %if.end ], [ %call2822, %land.lhs.true23 ], [ null, %if.then ]
2812  %tmp49 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8
2813  %call51 = call %struct._NSRange @objc_msgSend(ptr %call137, ptr %tmp49, i64 0, i64 0)
2814  %call513 = extractvalue %struct._NSRange %call51, 0
2815  %call514 = extractvalue %struct._NSRange %call51, 1
2816  %tmp52 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8
2817  %call548 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call137, ptr %tmp52, i64 %call513, i64 %call514)
2818  %tmp55 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8
2819  %tmp56 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8
2820  %call58 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp55, ptr %tmp56)
2821  %tmp59 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8
2822  %call6110 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call548, ptr %tmp59, ptr %call58)
2823  %tmp15 = call ptr @llvm.objc.retain(ptr %call6110) nounwind
2824  call void @llvm.objc.release(ptr %call137) nounwind
2825  %tmp64 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8
2826  %call66 = call signext i8 @objc_msgSend(ptr %call6110, ptr %tmp64, ptr @_unnamed_cfstring_44)
2827  %tobool67 = icmp eq i8 %call66, 0
2828  br i1 %tobool67, label %if.end74, label %if.then68
2829
2830if.then68:                                        ; preds = %if.then44
2831  %tmp70 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8
2832  %call7220 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call6110, ptr %tmp70)
2833  %tmp16 = call ptr @llvm.objc.retain(ptr %call7220) nounwind
2834  call void @llvm.objc.release(ptr %call6110) nounwind
2835  br label %if.end74
2836
2837if.end74:                                         ; preds = %if.then68, %if.then44
2838  %filename.0.in = phi ptr [ %call7220, %if.then68 ], [ %call6110, %if.then44 ]
2839  %tmp17 = load ptr, ptr @"\01l_objc_msgSend_fixup_isEqual_", align 16
2840  %call78 = call signext i8 (ptr, ptr, ptr, ...) %tmp17(ptr %call137, ptr @"\01l_objc_msgSend_fixup_isEqual_", ptr %filename.0.in)
2841  %tobool79 = icmp eq i8 %call78, 0
2842  br i1 %tobool79, label %land.lhs.true80, label %if.then109
2843
2844land.lhs.true80:                                  ; preds = %if.end74
2845  %tmp82 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
2846  %call84 = call signext i8 @objc_msgSend(ptr %filename.0.in, ptr %tmp82)
2847  %tobool86 = icmp eq i8 %call84, 0
2848  br i1 %tobool86, label %if.then109, label %if.end106
2849
2850if.end106:                                        ; preds = %land.lhs.true80
2851  %tmp88 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
2852  %tmp90 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
2853  %call9218 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp88, ptr %tmp90, ptr %filename.0.in)
2854  %tmp21 = call ptr @llvm.objc.retain(ptr %call9218) nounwind
2855  call void @llvm.objc.release(ptr %url.025) nounwind
2856  %tmp94 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
2857  %tmp95 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
2858  %call97 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp94, ptr %tmp95)
2859  %tmp99 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
2860  %call10119 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call97, ptr %tmp99, ptr %call9218, i32 signext 1, ptr %err)
2861  %phitmp = icmp eq ptr %call10119, null
2862  br i1 %phitmp, label %if.then109, label %end
2863
2864if.then109:                                       ; preds = %if.end106, %land.lhs.true80, %if.end74
2865  %url.129 = phi ptr [ %call9218, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ]
2866  %tmp110 = load ptr, ptr %err, align 8
2867  %tobool111 = icmp eq ptr %tmp110, null
2868  br i1 %tobool111, label %if.then112, label %if.end125
2869
2870if.then112:                                       ; preds = %if.then109
2871  %tmp113 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8
2872  %tmp114 = load ptr, ptr @NSCocoaErrorDomain, align 8
2873  %tmp115 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8
2874  %call117 = call ptr @truncatedString(ptr %filename.0.in, i64 1034)
2875  %tmp118 = load ptr, ptr @NSFilePathErrorKey, align 8
2876  %tmp119 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8
2877  %call12113 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp115, ptr %tmp119, ptr %call117, ptr %tmp118, ptr null)
2878  %tmp122 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8
2879  %call12414 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp113, ptr %tmp122, ptr %tmp114, i64 258, ptr %call12113)
2880  %tmp23 = call ptr @llvm.objc.retain(ptr %call12414) nounwind
2881  %tmp25 = call ptr @llvm.objc.autorelease(ptr %tmp23) nounwind
2882  store ptr %tmp25, ptr %err, align 8
2883  br label %if.end125
2884
2885if.end125:                                        ; preds = %if.then112, %if.then109
2886  %tmp127 = phi ptr [ %tmp110, %if.then109 ], [ %tmp25, %if.then112 ]
2887  %tmp126 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8
2888  %tmp128 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8
2889  %call13015 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp126, ptr %tmp128, ptr %tmp127)
2890  %tmp131 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8
2891  %call13317 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call13015, ptr %tmp131)
2892  br label %end
2893
2894end:                                              ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry
2895  %filename.2 = phi ptr [ %filename.0.in, %if.end106 ], [ %filename.0.in, %if.end125 ], [ %call137, %land.lhs.true ], [ null, %entry ], [ %call137, %if.end ]
2896  %origFilename.0 = phi ptr [ %call137, %if.end106 ], [ %call137, %if.end125 ], [ %call137, %land.lhs.true ], [ null, %entry ], [ %call137, %if.end ]
2897  %url.2 = phi ptr [ %call9218, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %call2822, %if.end ]
2898  call void @llvm.objc.release(ptr %tmp9) nounwind, !clang.imprecise_release !0
2899  call void @llvm.objc.release(ptr %url.2) nounwind, !clang.imprecise_release !0
2900  call void @llvm.objc.release(ptr %origFilename.0) nounwind, !clang.imprecise_release !0
2901  call void @llvm.objc.release(ptr %filename.2) nounwind, !clang.imprecise_release !0
2902  call void @llvm.objc.release(ptr %self) nounwind, !clang.imprecise_release !0
2903  ret void
2904}
2905
2906declare i32 @__gxx_personality_v0(...)
2907
2908declare i32 @llvm.objc.sync.enter(ptr)
2909declare i32 @llvm.objc.sync.exit(ptr)
2910
2911; Make sure that we understand that objc_sync_{enter,exit} are IC_User not
2912; IC_Call/IC_CallOrUser.
2913
2914; CHECK-LABEL:      define void @test67(
2915; CHECK-NEXT:   call i32 @llvm.objc.sync.enter(ptr %x)
2916; CHECK-NEXT:   call i32 @llvm.objc.sync.exit(ptr %x)
2917; CHECK-NEXT:   ret void
2918; CHECK-NEXT: }
2919define void @test67(ptr %x) {
2920  call ptr @llvm.objc.retain(ptr %x)
2921  call i32 @llvm.objc.sync.enter(ptr %x)
2922  call i32 @llvm.objc.sync.exit(ptr %x)
2923  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0
2924  ret void
2925}
2926
2927; CHECK-LABEL: define void @test68(
2928; CHECK-NOT:     call
2929; CHECK:         call void @callee2(
2930; CHECK-NOT:     call
2931; CHECK:         ret void
2932
2933define void @test68(ptr %a, ptr %b) {
2934  call ptr @llvm.objc.retain(ptr %a)
2935  call ptr @llvm.objc.retain(ptr %b)
2936  call void @callee2(ptr %a, ptr %b)
2937  call void @llvm.objc.release(ptr %b), !clang.imprecise_release !0
2938  call void @llvm.objc.release(ptr %a), !clang.imprecise_release !0
2939  ret void
2940}
2941
2942!llvm.module.flags = !{!1}
2943!llvm.dbg.cu = !{!3}
2944
2945!0 = !{}
2946!1 = !{i32 1, !"Debug Info Version", i32 3}
2947!2 = distinct !DISubprogram(unit: !3)
2948!3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
2949                             file: !4,
2950                             isOptimized: true, flags: "-O2",
2951                             splitDebugFilename: "abc.debug", emissionKind: 2)
2952!4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
2953!5 = !{i32 2, !"Debug Info Version", i32 3}
2954
2955; CHECK: attributes [[NUW]] = { nounwind }
2956; CHECK: ![[RELEASE]] = !{}
2957