1
1
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -Wno-return-stack-address -emit-cir %s -o %t.cir
2
2
// RUN: FileCheck --input-file=%t.cir %s
3
+ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -o - %s \
4
+ // RUN: | opt -S -passes=instcombine,mem2reg,simplifycfg -o %t.ll
5
+ // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
3
6
4
7
void fn () {
5
8
auto a = [](){};
@@ -15,6 +18,21 @@ void fn() {
15
18
// CHECK-NEXT: %0 = cir.alloca !ty_anon2E0_, !cir.ptr<!ty_anon2E0_>, ["a"]
16
19
// CHECK: cir.call @_ZZ2fnvENK3$_0clEv
17
20
21
+ // LLVM: {{.*}}void @"_ZZ2fnvENK3$_0clEv"(ptr [[THIS:%.*]])
22
+ // FIXME: argument attributes should be emmitted, and lambda's alignment
23
+ // COM: LLVM: {{.*}} @"_ZZ2fnvENK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]){{%.*}} align 2 {
24
+ // LLVM: [[THIS_ADDR:%.*]] = alloca ptr, i64 1, align 8
25
+ // LLVM: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
26
+ // LLVM: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
27
+ // LLVM: ret void
28
+
29
+ // LLVM-LABEL: _Z2fnv
30
+ // LLVM: [[a:%.*]] = alloca %class.anon.0, i64 1, align 1
31
+ // FIXME: parameter attributes should be emitted
32
+ // LLVM: call void @"_ZZ2fnvENK3$_0clEv"(ptr [[a]])
33
+ // COM: LLVM: call void @"_ZZ2fnvENK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) [[a]])
34
+ // LLVM: ret void
35
+
18
36
void l0 () {
19
37
int i;
20
38
auto a = [&](){ i = i + 1 ; };
@@ -37,6 +55,34 @@ void l0() {
37
55
38
56
// CHECK: cir.func @_Z2l0v()
39
57
58
+ // LLVM: {{.* }}void @"_ZZ2l0vENK3$_0clEv"(ptr [[THIS:%.*]])
59
+ // LLVM: [[THIS_ADDR:%.*]] = alloca ptr, i64 1, align 8
60
+ // LLVM: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
61
+ // LLVM: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
62
+ // LLVM: [[I:%.*]] = getelementptr %class.anon.2, ptr [[THIS1]], i32 0, i32 0
63
+ // FIXME: getelementptr argument attributes should be emitted
64
+ // COM: LLVM: [[I:%.*]] = getelementptr inbounds nuw %class.anon.0, ptr [[THIS1]], i32 0, i32 0
65
+ // LLVM: [[TMP0:%.*]] = load ptr, ptr [[I]], align 8
66
+ // LLVM: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
67
+ // LLVM: [[ADD:%.*]] = add nsw i32 [[TMP1]], 1
68
+ // LLVM: [[I:%.*]] = getelementptr %class.anon.2, ptr [[THIS1]], i32 0, i32
69
+ // COM: LLVM: [[I:%.*]] = getelementptr inbounds nuw %class.anon.0, ptr [[THIS1]], i32 0, i32 0
70
+ // LLVM: [[TMP4:%.*]] = load ptr, ptr [[I]], align 8
71
+ // LLVM: store i32 [[ADD]], ptr [[TMP4]], align 4
72
+ // LLVM: ret void
73
+
74
+ // LLVM-LABEL: _Z2l0v
75
+ // LLVM: [[i:%.*]] = alloca i32, i64 1, align 4
76
+ // LLVM: [[a:%.*]] = alloca %class.anon.2, i64 1, align 8
77
+ // FIXME: getelementptr argument attributes should be emitted
78
+ // COM: LLVM: [[TMP0:%.*]] = getelementptr inbounds %class.anon.2, ptr [[a]], i32 0, i32 0
79
+ // LLVM: [[TMP0:%.*]] = getelementptr %class.anon.2, ptr [[a]], i32 0, i32 0
80
+ // LLVM: store ptr [[i]], ptr [[TMP0]], align 8
81
+ // FIXME: parameter attributes should be emitted
82
+ // COM: LLVM: call void @"_ZZ2l0vENK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) [[a]])
83
+ // LLVM: call void @"_ZZ2l0vENK3$_0clEv"(ptr [[a]])
84
+ // LLVM: ret void
85
+
40
86
auto g () {
41
87
int i = 12 ;
42
88
return [&] {
@@ -55,6 +101,15 @@ auto g() {
55
101
// CHECK: %4 = cir.load %0 : !cir.ptr<!ty_anon2E3_>, !ty_anon2E3_
56
102
// CHECK: cir.return %4 : !ty_anon2E3_
57
103
104
+ // LLVM-LABEL: @_Z1gv()
105
+ // LLVM: [[retval:%.*]] = alloca %class.anon.3, i64 1, align 8
106
+ // LLVM: [[i:%.*]] = alloca i32, i64 1, align 4
107
+ // LLVM: store i32 12, ptr [[i]], align 4
108
+ // LLVM: [[i_addr:%.*]] = getelementptr %class.anon.3, ptr [[retval]], i32 0, i32 0
109
+ // LLVM: store ptr [[i]], ptr [[i_addr]], align 8
110
+ // LLVM: [[tmp:%.*]] = load %class.anon.3, ptr [[retval]], align 8
111
+ // LLVM: ret %class.anon.3 [[tmp]]
112
+
58
113
auto g2 () {
59
114
int i = 12 ;
60
115
auto lam = [&] {
@@ -75,6 +130,15 @@ auto g2() {
75
130
// CHECK-NEXT: %4 = cir.load %0 : !cir.ptr<!ty_anon2E4_>, !ty_anon2E4_
76
131
// CHECK-NEXT: cir.return %4 : !ty_anon2E4_
77
132
133
+ // LLVM-LABEL: @_Z2g2v()
134
+ // LLVM: [[retval:%.*]] = alloca %class.anon.4, i64 1, align 8
135
+ // LLVM: [[i:%.*]] = alloca i32, i64 1, align 4
136
+ // LLVM: store i32 12, ptr [[i]], align 4
137
+ // LLVM: [[i_addr:%.*]] = getelementptr %class.anon.4, ptr [[retval]], i32 0, i32 0
138
+ // LLVM: store ptr [[i]], ptr [[i_addr]], align 8
139
+ // LLVM: [[tmp:%.*]] = load %class.anon.4, ptr [[retval]], align 8
140
+ // LLVM: ret %class.anon.4 [[tmp]]
141
+
78
142
int f () {
79
143
return g2 ()();
80
144
}
@@ -92,6 +156,36 @@ int f() {
92
156
// CHECK-NEXT: cir.return %1 : !s32i
93
157
// CHECK-NEXT: }
94
158
159
+ // LLVM: {{.*}}i32 @"_ZZ2g2vENK3$_0clEv"(ptr [[THIS:%.*]])
160
+ // LLVM: [[THIS_ADDR:%.*]] = alloca ptr, i64 1, align 8
161
+ // LLVM: [[I_SAVE:%.*]] = alloca i32, i64 1, align 4
162
+ // LLVM: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
163
+ // LLVM: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
164
+ // LLVM: [[I:%.*]] = getelementptr %class.anon.4, ptr [[THIS1]], i32 0, i32 0
165
+ // LLVM: [[TMP0:%.*]] = load ptr, ptr [[I]], align 8
166
+ // LLVM: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
167
+ // LLVM: [[ADD:%.*]] = add nsw i32 [[TMP1]], 100
168
+ // LLVM: [[I:%.*]] = getelementptr %class.anon.4, ptr [[THIS1]], i32 0, i32 0
169
+ // LLVM: [[TMP4:%.*]] = load ptr, ptr [[I]], align 8
170
+ // LLVM: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
171
+ // LLVM: store i32 [[TMP5]], ptr [[I_SAVE]], align 4
172
+ // LLVM: [[TMP6:%.*]] = load i32, ptr [[I_SAVE]], align 4
173
+ // LLVM: ret i32 [[TMP6]]
174
+
175
+ // LLVM-LABEL: _Z1fv
176
+ // LLVM: [[ref_tmp0:%.*]] = alloca %class.anon.4, i64 1, align 8
177
+ // LLVM: [[ret_val:%.*]] = alloca i32, i64 1, align 4
178
+ // LLVM: br label %[[scope_bb:[0-9]+]],
179
+ // LLVM: [[scope_bb]]:
180
+ // LLVM: [[tmp0:%.*]] = call %class.anon.4 @_Z2g2v()
181
+ // LLVM: store %class.anon.4 [[tmp0]], ptr [[ref_tmp0]], align 8
182
+ // LLVM: [[tmp1:%.*]] = call i32 @"_ZZ2g2vENK3$_0clEv"(ptr [[ref_tmp0]])
183
+ // LLVM: store i32 [[tmp1]], ptr [[ret_val]], align 4
184
+ // LLVM: br label %[[ret_bb:[0-9]+]],
185
+ // LLVM: [[ret_bb]]:
186
+ // LLVM: [[tmp2:%.*]] = load i32, ptr [[ret_val]], align 4
187
+ // LLVM: ret i32 [[tmp2]]
188
+
95
189
int g3 () {
96
190
auto * fn = +[](int const & i) -> int { return i; };
97
191
auto task = fn (3 );
@@ -134,3 +228,60 @@ int g3() {
134
228
// CHECK: }
135
229
136
230
// CHECK: }
231
+
232
+ // lambda operator()
233
+ // FIXME: argument attributes should be emitted
234
+ // COM: LLVM: define internal noundef i32 @"_ZZ2g3vENK3$_0clERKi"(ptr noundef nonnull align 1 dereferenceable(1) {{%.*}}, ptr noundef nonnull align 4 dereferenceable(4){{%.*}}) #0 align 2
235
+ // LLVM: {{.*}}i32 @"_ZZ2g3vENK3$_0clERKi"(ptr {{%.*}}, ptr {{%.*}})
236
+
237
+ // lambda __invoke()
238
+ // LLVM: {{.*}}i32 @"_ZZ2g3vEN3$_08__invokeERKi"(ptr [[i:%.*]])
239
+ // LLVM: [[i_addr:%.*]] = alloca ptr, i64 1, align 8
240
+ // LLVM: [[ret_val:%.*]] = alloca i32, i64 1, align 4
241
+ // LLVM: [[unused_capture:%.*]] = alloca %class.anon.5, i64 1, align 1
242
+ // LLVM: store ptr [[i]], ptr [[i_addr]], align 8
243
+ // LLVM: [[TMP0:%.*]] = load ptr, ptr [[i_addr]], align 8
244
+ // FIXME: call and argument attributes should be emitted
245
+ // COM: LLVM: [[CALL:%.*]] = call noundef i32 @"_ZZ2g3vENK3$_0clERKi"(ptr noundef nonnull align 1 dereferenceable(1) [[unused_capture]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]])
246
+ // LLVM: [[CALL:%.*]] = call i32 @"_ZZ2g3vENK3$_0clERKi"(ptr [[unused_capture]], ptr [[TMP0]])
247
+ // LLVM: store i32 [[CALL]], ptr [[ret_val]], align 4
248
+ // FIXME: should just return result
249
+ // COM: LLVM: ret i32 [[ret_val]]
250
+ // LLVM: call void @llvm.trap()
251
+ // LLVM: unreachable
252
+
253
+ // lambda operator int (*)(int const&)()
254
+ // LLVM-LABEL: @"_ZZ2g3vENK3$_0cvPFiRKiEEv"
255
+ // LLVM: store ptr @"_ZZ2g3vEN3$_08__invokeERKi", ptr [[ret_val:%.*]], align 8
256
+ // LLVM: [[TMP0:%.*]] = load ptr, ptr [[ret_val]], align 8
257
+ // LLVM: ret ptr [[TMP0]]
258
+
259
+ // LLVM-LABEL: _Z2g3v
260
+ // LLVM-DAG: [[ref_tmp0:%.*]] = alloca %class.anon.5, i64 1, align 1
261
+ // LLVM-DAG: [[ref_tmp1:%.*]] = alloca i32, i64 1, align 4
262
+ // LLVM-DAG: [[ret_val:%.*]] = alloca i32, i64 1, align 4
263
+ // LLVM-DAG: [[fn_ptr:%.*]] = alloca ptr, i64 1, align 8
264
+ // LLVM-DAG: [[task:%.*]] = alloca i32, i64 1, align 4
265
+ // LLVM: br label %[[scope0_bb:[0-9]+]],
266
+
267
+ // LLVM: [[scope0_bb]]: {{.*}}; preds = %0
268
+ // LLVM: [[call:%.*]] = call ptr @"_ZZ2g3vENK3$_0cvPFiRKiEEv"(ptr [[ref_tmp0]])
269
+ // LLVM: br label %[[scope1_before:[0-9]+]],
270
+
271
+ // LLVM: [[scope1_before]]: {{.*}}; preds = %[[scope0_bb]]
272
+ // LLVM: [[tmp0:%.*]] = phi ptr [ [[call]], %[[scope0_bb]] ]
273
+ // LLVM: br label %[[scope1_bb:[0-9]+]],
274
+
275
+ // LLVM: [[scope1_bb]]: {{.*}}; preds = %[[scope1_before]]
276
+ // LLVM: [[fn:%.*]] = load ptr, ptr [[fn_ptr]], align 8
277
+ // LLVM: store i32 3, ptr [[ref_tmp1]], align 4
278
+ // LLVM: [[call1:%.*]] = call i32 [[fn]](ptr [[ref_tmp1]])
279
+ // LLVM: br label %[[ret_bb:[0-9]+]],
280
+
281
+ // LLVM: [[ret_bb]]: {{.*}}; preds = %[[scope1_bb]]
282
+ // LLVM: [[tmp1:%.*]] = phi i32 [ [[call1]], %[[scope1_bb]] ]
283
+ // LLVM: store i32 [[tmp1]], ptr [[task]], align 4
284
+ // LLVM: [[tmp2:%.*]] = load i32, ptr [[task]], align 4
285
+ // LLVM: store i32 [[tmp2]], ptr [[ret_val]], align 4
286
+ // LLVM: [[tmp3:%.*]] = load i32, ptr [[ret_val]], align 4
287
+ // LLVM: ret i32 [[tmp3]]
0 commit comments