1 // REQUIRES: amdgpu-registered-target
2 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fno-experimental-new-pass-manager -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
3 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fno-experimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,CHECK-LEGACY-OPT
4 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 -fno-experimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,CHECK-LEGACY-OPT
5 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fexperimental-new-pass-manager -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
6 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fexperimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,X64-NEWPM-OPT
7 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 -fexperimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,AMDGCN-NEWPM-OPT
8
9 namespace {
10
11 static int ctorcalls;
12 static int dtorcalls;
13
14 struct A {
A__anon30e720960111::A15 A() : i(0) { ctorcalls++; }
~A__anon30e720960111::A16 ~A() { dtorcalls++; }
17 int i;
18
operator <<(const A & a,int n)19 friend const A& operator<<(const A& a, int n) {
20 return a;
21 }
22 };
23
g(int)24 void g(int) { }
g(const A &)25 void g(const A&) { }
26
f1(bool b)27 void f1(bool b) {
28 g(b ? A().i : 0);
29 g(b || A().i);
30 g(b && A().i);
31 g(b ? A() << 1 : A() << 2);
32 }
33
34 struct Checker {
Checker__anon30e720960111::Checker35 Checker() {
36 f1(true);
37 f1(false);
38 }
39 };
40
41 Checker c;
42
43 }
44
45 // CHECK-OPT-LABEL: define i32 @_Z12getCtorCallsv()
getCtorCalls()46 int getCtorCalls() {
47 // CHECK-LEGACY-OPT: ret i32 5
48 // X64-NEWPM-OPT: ret i32 5
49 // AMDGCN-NEWPM-OPT: [[RET:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19ctorcallsE to i32*), align 4
50 // AMDGCN-NEWPM-OPT: ret i32 [[RET]]
51 return ctorcalls;
52 }
53
54 // CHECK-OPT-LABEL: define i32 @_Z12getDtorCallsv()
getDtorCalls()55 int getDtorCalls() {
56 // CHECK-LEGACY-OPT: ret i32 5
57 // X64-NEWPM-OPT: ret i32 5
58 // AMDGCN-NEWPM-OPT: [[RET:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19dtorcallsE to i32*), align 4
59 // AMDGCN-NEWPM-OPT: ret i32 [[RET]]
60 return dtorcalls;
61 }
62
63 // CHECK-OPT-LABEL: define zeroext i1 @_Z7successv()
success()64 bool success() {
65 // CHECK-LEGACY-OPT: ret i1 true
66 // X64-NEWPM-OPT: ret i1 true
67 // AMDGCN-NEWPM-OPT: [[CTORS:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19ctorcallsE to i32*), align 4, !tbaa !2
68 // AMDGCN-NEWPM-OPT: [[DTORS:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19dtorcallsE to i32*), align 4, !tbaa !2
69 // AMDGCN-NEWPM-OPT: %cmp = icmp eq i32 [[CTORS]], [[DTORS]]
70 // AMDGCN-NEWPM-OPT: ret i1 %cmp
71 return ctorcalls == dtorcalls;
72 }
73
74 struct X { ~X(); int f(); };
75 int g(int, int, int);
76 // CHECK-LABEL: @_Z16lifetime_nontriv
lifetime_nontriv(bool cond)77 int lifetime_nontriv(bool cond) {
78 // CHECK-NOOPT: store i1 false,
79 // CHECK-NOOPT: store i1 false,
80 // CHECK-NOOPT: store i1 false,
81 // CHECK-NOOPT: store i1 false,
82 // CHECK-NOOPT: store i1 false,
83 // CHECK-NOOPT: store i1 false,
84 // CHECK-NOOPT: br i1
85 //
86 // CHECK-NOOPT: call void @llvm.lifetime.start
87 // CHECK-NOOPT: store i1 true,
88 // CHECK-NOOPT: store i1 true,
89 // CHECK-NOOPT: call i32 @_ZN1X1fEv(
90 // CHECK-NOOPT: call void @llvm.lifetime.start
91 // CHECK-NOOPT: store i1 true,
92 // CHECK-NOOPT: store i1 true,
93 // CHECK-NOOPT: call i32 @_ZN1X1fEv(
94 // CHECK-NOOPT: call void @llvm.lifetime.start
95 // CHECK-NOOPT: store i1 true,
96 // CHECK-NOOPT: store i1 true,
97 // CHECK-NOOPT: call i32 @_ZN1X1fEv(
98 // CHECK-NOOPT: call i32 @_Z1giii(
99 // CHECK-NOOPT: br label
100 //
101 // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3)
102 // CHECK-NOOPT: br label
103 //
104 // CHECK-NOOPT: load i1,
105 // CHECK-NOOPT: br i1
106 // CHECK-NOOPT: call void @_ZN1XD1Ev(
107 // CHECK-NOOPT: br label
108 //
109 // CHECK-NOOPT: load i1,
110 // CHECK-NOOPT: br i1
111 // CHECK-NOOPT: call void @llvm.lifetime.end
112 // CHECK-NOOPT: br label
113 //
114 // CHECK-NOOPT: load i1,
115 // CHECK-NOOPT: br i1
116 // CHECK-NOOPT: call void @_ZN1XD1Ev(
117 // CHECK-NOOPT: br label
118 //
119 // CHECK-NOOPT: load i1,
120 // CHECK-NOOPT: br i1
121 // CHECK-NOOPT: call void @llvm.lifetime.end
122 // CHECK-NOOPT: br label
123 //
124 // CHECK-NOOPT: load i1,
125 // CHECK-NOOPT: br i1
126 // CHECK-NOOPT: call void @_ZN1XD1Ev(
127 // CHECK-NOOPT: br label
128 //
129 // CHECK-NOOPT: load i1,
130 // CHECK-NOOPT: br i1
131 // CHECK-NOOPT: call void @llvm.lifetime.end
132 // CHECK-NOOPT: br label
133 //
134 // CHECK-NOOPT: ret
135
136 // CHECK-OPT: br i1
137 //
138 // CHECK-OPT: call void @llvm.lifetime.start
139 // CHECK-OPT: call i32 @_ZN1X1fEv(
140 // CHECK-OPT: call void @llvm.lifetime.start
141 // CHECK-OPT: call i32 @_ZN1X1fEv(
142 // CHECK-OPT: call void @llvm.lifetime.start
143 // CHECK-OPT: call i32 @_ZN1X1fEv(
144 // CHECK-OPT: call i32 @_Z1giii(
145 // CHECK-OPT: call void @_ZN1XD1Ev(
146 // CHECK-OPT: call void @llvm.lifetime.end
147 // CHECK-OPT: call void @_ZN1XD1Ev(
148 // CHECK-OPT: call void @llvm.lifetime.end
149 // CHECK-OPT: call void @_ZN1XD1Ev(
150 // CHECK-OPT: call void @llvm.lifetime.end
151 // CHECK-OPT: br label
152 return cond ? g(X().f(), X().f(), X().f()) : g(1, 2, 3);
153 }
154
155 struct Y { int f(); };
156 int g(int, int, int);
157 // CHECK-LABEL: @_Z13lifetime_triv
lifetime_triv(bool cond)158 int lifetime_triv(bool cond) {
159 // CHECK-NOOPT: call void @llvm.lifetime.start
160 // CHECK-NOOPT: call void @llvm.lifetime.start
161 // CHECK-NOOPT: call void @llvm.lifetime.start
162 // CHECK-NOOPT: br i1
163 //
164 // CHECK-NOOPT: call i32 @_ZN1Y1fEv(
165 // CHECK-NOOPT: call i32 @_ZN1Y1fEv(
166 // CHECK-NOOPT: call i32 @_ZN1Y1fEv(
167 // CHECK-NOOPT: call i32 @_Z1giii(
168 // CHECK-NOOPT: br label
169 //
170 // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3)
171 // CHECK-NOOPT: br label
172 //
173 // CHECK-NOOPT: call void @llvm.lifetime.end
174 // CHECK-NOOPT-NOT: br
175 // CHECK-NOOPT: call void @llvm.lifetime.end
176 // CHECK-NOOPT-NOT: br
177 // CHECK-NOOPT: call void @llvm.lifetime.end
178 //
179 // CHECK-NOOPT: ret
180
181 // FIXME: LLVM isn't smart enough to remove the lifetime markers from the
182 // g(1, 2, 3) path here.
183
184 // CHECK-OPT: call void @llvm.lifetime.start
185 // CHECK-OPT: call void @llvm.lifetime.start
186 // CHECK-OPT: call void @llvm.lifetime.start
187 // CHECK-OPT: br i1
188 //
189 // CHECK-OPT: call i32 @_ZN1Y1fEv(
190 // CHECK-OPT: call i32 @_ZN1Y1fEv(
191 // CHECK-OPT: call i32 @_ZN1Y1fEv(
192 // CHECK-OPT: call i32 @_Z1giii(
193 // CHECK-OPT: br label
194 //
195 // CHECK-OPT: call void @llvm.lifetime.end
196 // CHECK-OPT: call void @llvm.lifetime.end
197 // CHECK-OPT: call void @llvm.lifetime.end
198 return cond ? g(Y().f(), Y().f(), Y().f()) : g(1, 2, 3);
199 }
200
~ZZ201 struct Z { ~Z() {} int f(); };
202 int g(int, int, int);
203 // CHECK-LABEL: @_Z22lifetime_nontriv_empty
lifetime_nontriv_empty(bool cond)204 int lifetime_nontriv_empty(bool cond) {
205 // CHECK-OPT: br i1
206 //
207 // CHECK-OPT: call void @llvm.lifetime.start
208 // CHECK-OPT: call i32 @_ZN1Z1fEv(
209 // CHECK-OPT: call void @llvm.lifetime.start
210 // CHECK-OPT: call i32 @_ZN1Z1fEv(
211 // CHECK-OPT: call void @llvm.lifetime.start
212 // CHECK-OPT: call i32 @_ZN1Z1fEv(
213 // CHECK-OPT: call i32 @_Z1giii(
214 // CHECK-OPT: call void @llvm.lifetime.end
215 // CHECK-OPT: call void @llvm.lifetime.end
216 // CHECK-OPT: call void @llvm.lifetime.end
217 // CHECK-OPT: br label
218 return cond ? g(Z().f(), Z().f(), Z().f()) : g(1, 2, 3);
219 }
220