[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Inline / inline-retainRV-call.ll
blobf8ac2154f9339d75130e2497f1a7d178056d1a72
1 ; RUN: opt < %s -inline -S | FileCheck %s
3 @g0 = global i8* null, align 8
4 declare i8* @foo0()
6 define i8* @callee0_autoreleaseRV() {
7   %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
8   %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
9   ret i8* %call
12 ; CHECK-LABEL: define void @test0_autoreleaseRV(
13 ; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
15 define void @test0_autoreleaseRV() {
16   %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
17   ret void
20 ; CHECK-LABEL: define void @test0_claimRV_autoreleaseRV(
21 ; CHECK: %[[CALL:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
22 ; CHECK: call void @llvm.objc.release(i8* %[[CALL]])
23 ; CHECK-NEXT: ret void
25 define void @test0_claimRV_autoreleaseRV() {
26   %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
27   ret void
30 ; CHECK-LABEL: define void @test1_autoreleaseRV(
31 ; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
33 define void @test1_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
34 entry:
35   %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
36           to label %invoke.cont unwind label %lpad
38 invoke.cont:
39   ret void
41 lpad:
42   %0 = landingpad { i8*, i32 }
43           cleanup
44   resume { i8*, i32 } undef
47 ; CHECK-LABEL: define void @test1_claimRV_autoreleaseRV(
48 ; CHECK: %[[INVOKE:.*]] = invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
49 ; CHECK: call void @llvm.objc.release(i8* %[[INVOKE]])
50 ; CHECK-NEXT: br
52 define void @test1_claimRV_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
53 entry:
54   %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
55           to label %invoke.cont unwind label %lpad
57 invoke.cont:
58   ret void
60 lpad:
61   %0 = landingpad { i8*, i32 }
62           cleanup
63   resume { i8*, i32 } undef
66 define i8* @callee1_no_autoreleaseRV() {
67   %call = call i8* @foo0()
68   ret i8* %call
71 ; CHECK-LABEL: define void @test2_no_autoreleaseRV(
72 ; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
73 ; CHECK-NEXT: ret void
75 define void @test2_no_autoreleaseRV() {
76   %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
77   ret void
80 ; CHECK-LABEL: define void @test2_claimRV_no_autoreleaseRV(
81 ; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 1) ]
82 ; CHECK-NEXT: ret void
84 define void @test2_claimRV_no_autoreleaseRV() {
85   %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
86   ret void
89 ; CHECK-LABEL: define void @test3_no_autoreleaseRV(
90 ; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
92 define void @test3_no_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
93 entry:
94   %call = invoke i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
95           to label %invoke.cont unwind label %lpad
97 invoke.cont:
98   ret void
100 lpad:
101   %0 = landingpad { i8*, i32 }
102           cleanup
103   resume { i8*, i32 } undef
106 define i8* @callee2_nocall() {
107   %1 = load i8*, i8** @g0, align 8
108   ret i8* %1
111 ; Check that a call to @llvm.objc.retain is inserted if there is no matching
112 ; autoreleaseRV call or a call.
114 ; CHECK-LABEL: define void @test4_nocall(
115 ; CHECK: %[[V0:.*]] = load i8*, i8** @g0,
116 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])
117 ; CHECK-NEXT: ret void
119 define void @test4_nocall() {
120   %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 0) ]
121   ret void
124 ; CHECK-LABEL: define void @test4_claimRV_nocall(
125 ; CHECK: %[[V0:.*]] = load i8*, i8** @g0,
126 ; CHECK-NEXT: ret void
128 define void @test4_claimRV_nocall() {
129   %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 1) ]
130   ret void
133 ; Check that a call to @llvm.objc.retain is inserted if call to @foo already has
134 ; the attribute. I'm not sure this will happen in practice.
136 define i8* @callee3_marker() {
137   %1 = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
138   ret i8* %1
141 ; CHECK-LABEL: define void @test5(
142 ; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
143 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])
144 ; CHECK-NEXT: ret void
146 define void @test5() {
147   %call = call i8* @callee3_marker() [ "clang.arc.attachedcall"(i64 0) ]
148   ret void
151 ; Don't pair up an autoreleaseRV in the callee and an retainRV in the caller
152 ; if there is an instruction between the ret instruction and the call to
153 ; autoreleaseRV that isn't a cast instruction.
155 define i8* @callee0_autoreleaseRV2() {
156   %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
157   %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
158   store i8* null, i8** @g0
159   ret i8* %call
162 ; CHECK-LABEL: define void @test6(
163 ; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
164 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V0]])
165 ; CHECK: store i8* null, i8** @g0, align 8
166 ; CHECK: call i8* @llvm.objc.retain(i8* %[[V0]])
167 ; CHECK-NEXT: ret void
169 define void @test6() {
170   %call = call i8* @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(i64 0) ]
171   ret void
174 declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
175 declare i32 @__gxx_personality_v0(...)