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