Skip to content

Commit c536967

Browse files
committed
Split _Countof tests into two files; NFC
Post-commit review feedback during the language WG meeting requested that I try to generalize the testing for this rather than only test on a single target as we previously did. The tests which are hard to generalize are the VLA tests, so those still have specific triples in the RUN line, but have more coverage and a comment explaining that the test should generalize to all targets.
1 parent eafbb87 commit c536967

File tree

2 files changed

+178
-102
lines changed

2 files changed

+178
-102
lines changed

clang/test/C/C2y/n3369_2.c

Lines changed: 12 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,26 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2-
// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
2+
// RUN: %clang_cc1 -std=c2y -emit-llvm -o - %s | FileCheck %s
33

4-
// This tests the codegen behavior for _Countof.
5-
// CHECK-LABEL: define dso_local i32 @test1(
4+
// This tests the non-VLA codegen behavior for _Countof.
5+
6+
typedef typeof(sizeof(0)) size_t;
7+
8+
// CHECK-LABEL: define dso_local i64 @test1(
69
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
710
// CHECK-NEXT: [[ENTRY:.*:]]
8-
// CHECK-NEXT: [[ARRAY:%.*]] = alloca [12 x i32], align 16
9-
// CHECK-NEXT: ret i32 12
11+
// CHECK-NEXT: [[ARRAY:%.*]] = alloca [12 x i32], align
12+
// CHECK-NEXT: ret i64 12
1013
//
11-
int test1() {
14+
size_t test1() {
1215
int array[12];
1316
return _Countof(array);
1417
}
1518

16-
// CHECK-LABEL: define dso_local i32 @test2(
17-
// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
18-
// CHECK-NEXT: [[ENTRY:.*:]]
19-
// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
20-
// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8
21-
// CHECK-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align 8
22-
// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
23-
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
24-
// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
25-
// CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
26-
// CHECK-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8
27-
// CHECK-NEXT: [[VLA:%.*]] = alloca i32, i64 [[TMP1]], align 16
28-
// CHECK-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8
29-
// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32
30-
// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8
31-
// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP3]])
32-
// CHECK-NEXT: ret i32 [[CONV]]
33-
//
34-
int test2(int n) {
35-
int array[n];
36-
return _Countof(array);
37-
}
38-
39-
// CHECK-LABEL: define dso_local i32 @test3(
40-
// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
41-
// CHECK-NEXT: [[ENTRY:.*:]]
42-
// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
43-
// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
44-
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
45-
// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
46-
// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32
47-
// CHECK-NEXT: ret i32 [[CONV]]
48-
//
49-
int test3(int n) {
50-
return _Countof(int[n]);
51-
}
52-
53-
// CHECK-LABEL: define dso_local i32 @test4(
19+
// CHECK-LABEL: define dso_local i64 @test2(
5420
// CHECK-SAME: ) #[[ATTR0]] {
5521
// CHECK-NEXT: [[ENTRY:.*:]]
56-
// CHECK-NEXT: ret i32 100
22+
// CHECK-NEXT: ret i64 100
5723
//
58-
int test4() {
24+
size_t test2() {
5925
return _Countof(float[100]);
6026
}
61-
62-
// CHECK-LABEL: define dso_local i32 @test5(
63-
// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
64-
// CHECK-NEXT: [[ENTRY:.*:]]
65-
// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
66-
// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8
67-
// CHECK-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align 8
68-
// CHECK-NEXT: [[X:%.*]] = alloca i32, align 4
69-
// CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4
70-
// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
71-
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
72-
// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
73-
// CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
74-
// CHECK-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8
75-
// CHECK-NEXT: [[VLA:%.*]] = alloca [7 x i32], i64 [[TMP1]], align 16
76-
// CHECK-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8
77-
// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32
78-
// CHECK-NEXT: store i32 [[CONV]], ptr [[X]], align 4
79-
// CHECK-NEXT: store i32 7, ptr [[Y]], align 4
80-
// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[X]], align 4
81-
// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[Y]], align 4
82-
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP4]]
83-
// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8
84-
// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP5]])
85-
// CHECK-NEXT: ret i32 [[ADD]]
86-
//
87-
int test5(int n) {
88-
int array[n][7];
89-
int x = _Countof(array);
90-
int y = _Countof(*array);
91-
return x + y;
92-
}
93-
94-
// CHECK-LABEL: define dso_local void @test6(
95-
// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
96-
// CHECK-NEXT: [[ENTRY:.*:]]
97-
// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
98-
// CHECK-NEXT: [[X:%.*]] = alloca i32, align 4
99-
// CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4
100-
// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
101-
// CHECK-NEXT: store i32 7, ptr [[X]], align 4
102-
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4
103-
// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1
104-
// CHECK-NEXT: store i32 [[INC]], ptr [[N_ADDR]], align 4
105-
// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
106-
// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32
107-
// CHECK-NEXT: store i32 [[CONV]], ptr [[Y]], align 4
108-
// CHECK-NEXT: ret void
109-
//
110-
void test6(int n) {
111-
// n should not be evaluated in this case because the operator does not need
112-
// to evaluate it to know the result is 7.
113-
int x = _Countof(int[7][n++]);
114-
// n should be evaluated in this case, however.
115-
int y = _Countof(int[n++][7]);
116-
}

clang/test/C/C2y/n3369_3.c

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-64
3+
// RUN: %clang_cc1 -std=c2y -triple aarch64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-64
4+
// RUN: %clang_cc1 -std=c2y -triple ppc64le-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-64
5+
// RUN: %clang_cc1 -std=c2y -triple i686-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-32
6+
7+
// This tests the codegen behavior for VLA use in _Countof, which builds upon
8+
// the code generation for sizeof. It tests a limited set of triples due to
9+
// variations in VLA handling between platforms, but this test should
10+
// generalize to all targets.
11+
12+
typedef typeof(sizeof(0)) size_t;
13+
14+
// CHECK-64-LABEL: define dso_local i64 @test1(
15+
// CHECK-64-SAME: i32 noundef{{( signext)?}} [[N:%.*]]) #[[ATTR0:[0-9]+]] {
16+
// CHECK-64-NEXT: [[ENTRY:.*:]]
17+
// CHECK-64-NEXT: [[N_ADDR:%.*]] = alloca i32, align
18+
// CHECK-64-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align
19+
// CHECK-64-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align
20+
// CHECK-64-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
21+
// CHECK-64-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
22+
// CHECK-64-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
23+
// CHECK-64-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
24+
// CHECK-64-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align
25+
// CHECK-64-NEXT: [[VLA:%.*]] = alloca i32, i64 [[TMP1]], align
26+
// CHECK-64-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align
27+
// CHECK-64-NEXT: [[TMP3:%.*]] = load ptr, ptr [[SAVED_STACK]], align
28+
// CHECK-64-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP3]])
29+
// CHECK-64-NEXT: ret i64 [[TMP1]]
30+
//
31+
// CHECK-32-LABEL: define dso_local i32 @test1(
32+
// CHECK-32-SAME: i32 noundef [[N:%.*]]) #[[ATTR0:[0-9]+]] {
33+
// CHECK-32-NEXT: [[ENTRY:.*:]]
34+
// CHECK-32-NEXT: [[N_ADDR:%.*]] = alloca i32, align
35+
// CHECK-32-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align
36+
// CHECK-32-NEXT: [[__VLA_EXPR0:%.*]] = alloca i32, align
37+
// CHECK-32-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
38+
// CHECK-32-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
39+
// CHECK-32-NEXT: [[TMP1:%.*]] = call ptr @llvm.stacksave.p0()
40+
// CHECK-32-NEXT: store ptr [[TMP1]], ptr [[SAVED_STACK]], align
41+
// CHECK-32-NEXT: [[VLA:%.*]] = alloca i32, i32 [[TMP0]], align
42+
// CHECK-32-NEXT: store i32 [[TMP0]], ptr [[__VLA_EXPR0]], align
43+
// CHECK-32-NEXT: [[TMP2:%.*]] = load ptr, ptr [[SAVED_STACK]], align
44+
// CHECK-32-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP2]])
45+
// CHECK-32-NEXT: ret i32 [[TMP0]]
46+
//
47+
size_t test1(int n) {
48+
int array[n];
49+
return _Countof(array);
50+
}
51+
52+
// CHECK-64-LABEL: define dso_local i64 @test2(
53+
// CHECK-64-SAME: i32 noundef{{( signext)?}} [[N:%.*]]) #[[ATTR0]] {
54+
// CHECK-64-NEXT: [[ENTRY:.*:]]
55+
// CHECK-64-NEXT: [[N_ADDR:%.*]] = alloca i32, align
56+
// CHECK-64-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
57+
// CHECK-64-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
58+
// CHECK-64-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
59+
// CHECK-64-NEXT: ret i64 [[TMP1]]
60+
//
61+
// CHECK-32-LABEL: define dso_local i32 @test2(
62+
// CHECK-32-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
63+
// CHECK-32-NEXT: [[ENTRY:.*:]]
64+
// CHECK-32-NEXT: [[N_ADDR:%.*]] = alloca i32, align
65+
// CHECK-32-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
66+
// CHECK-32-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
67+
// CHECK-32-NEXT: ret i32 [[TMP0]]
68+
//
69+
size_t test2(int n) {
70+
return _Countof(int[n]);
71+
}
72+
73+
// CHECK-64-LABEL: define dso_local i64 @test3(
74+
// CHECK-64-SAME: i32 noundef{{( signext)?}} [[N:%.*]]) #[[ATTR0]] {
75+
// CHECK-64-NEXT: [[ENTRY:.*:]]
76+
// CHECK-64-NEXT: [[N_ADDR:%.*]] = alloca i32, align
77+
// CHECK-64-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align
78+
// CHECK-64-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align
79+
// CHECK-64-NEXT: [[X:%.*]] = alloca i32, align
80+
// CHECK-64-NEXT: [[Y:%.*]] = alloca i32, align
81+
// CHECK-64-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
82+
// CHECK-64-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
83+
// CHECK-64-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
84+
// CHECK-64-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0()
85+
// CHECK-64-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align
86+
// CHECK-64-NEXT: [[VLA:%.*]] = alloca [7 x i32], i64 [[TMP1]], align
87+
// CHECK-64-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align
88+
// CHECK-64-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32
89+
// CHECK-64-NEXT: store i32 [[CONV]], ptr [[X]], align
90+
// CHECK-64-NEXT: store i32 7, ptr [[Y]], align
91+
// CHECK-64-NEXT: [[TMP3:%.*]] = load i32, ptr [[X]], align
92+
// CHECK-64-NEXT: [[TMP4:%.*]] = load i32, ptr [[Y]], align
93+
// CHECK-64-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP4]]
94+
// CHECK-64-NEXT: [[CONV1:%.*]] = sext i32 [[ADD]] to i64
95+
// CHECK-64-NEXT: [[TMP5:%.*]] = load ptr, ptr [[SAVED_STACK]], align
96+
// CHECK-64-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP5]])
97+
// CHECK-64-NEXT: ret i64 [[CONV1]]
98+
//
99+
// CHECK-32-LABEL: define dso_local i32 @test3(
100+
// CHECK-32-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
101+
// CHECK-32-NEXT: [[ENTRY:.*:]]
102+
// CHECK-32-NEXT: [[N_ADDR:%.*]] = alloca i32, align
103+
// CHECK-32-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align
104+
// CHECK-32-NEXT: [[__VLA_EXPR0:%.*]] = alloca i32, align
105+
// CHECK-32-NEXT: [[X:%.*]] = alloca i32, align
106+
// CHECK-32-NEXT: [[Y:%.*]] = alloca i32, align
107+
// CHECK-32-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
108+
// CHECK-32-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
109+
// CHECK-32-NEXT: [[TMP1:%.*]] = call ptr @llvm.stacksave.p0()
110+
// CHECK-32-NEXT: store ptr [[TMP1]], ptr [[SAVED_STACK]], align
111+
// CHECK-32-NEXT: [[VLA:%.*]] = alloca [7 x i32], i32 [[TMP0]], align
112+
// CHECK-32-NEXT: store i32 [[TMP0]], ptr [[__VLA_EXPR0]], align
113+
// CHECK-32-NEXT: store i32 [[TMP0]], ptr [[X]], align
114+
// CHECK-32-NEXT: store i32 7, ptr [[Y]], align
115+
// CHECK-32-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align
116+
// CHECK-32-NEXT: [[TMP3:%.*]] = load i32, ptr [[Y]], align
117+
// CHECK-32-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[TMP3]]
118+
// CHECK-32-NEXT: [[TMP4:%.*]] = load ptr, ptr [[SAVED_STACK]], align
119+
// CHECK-32-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP4]])
120+
// CHECK-32-NEXT: ret i32 [[ADD]]
121+
//
122+
size_t test3(int n) {
123+
int array[n][7];
124+
int x = _Countof(array);
125+
int y = _Countof(*array);
126+
return x + y;
127+
}
128+
129+
// CHECK-64-LABEL: define dso_local void @test4(
130+
// CHECK-64-SAME: i32 noundef{{( signext)?}} [[N:%.*]]) #[[ATTR0]] {
131+
// CHECK-64-NEXT: [[ENTRY:.*:]]
132+
// CHECK-64-NEXT: [[N_ADDR:%.*]] = alloca i32, align
133+
// CHECK-64-NEXT: [[X:%.*]] = alloca i32, align
134+
// CHECK-64-NEXT: [[Y:%.*]] = alloca i32, align
135+
// CHECK-64-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
136+
// CHECK-64-NEXT: store i32 7, ptr [[X]], align
137+
// CHECK-64-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
138+
// CHECK-64-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1
139+
// CHECK-64-NEXT: store i32 [[INC]], ptr [[N_ADDR]], align
140+
// CHECK-64-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
141+
// CHECK-64-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32
142+
// CHECK-64-NEXT: store i32 [[CONV]], ptr [[Y]], align
143+
// CHECK-64-NEXT: ret void
144+
//
145+
// CHECK-32-LABEL: define dso_local void @test4(
146+
// CHECK-32-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
147+
// CHECK-32-NEXT: [[ENTRY:.*:]]
148+
// CHECK-32-NEXT: [[N_ADDR:%.*]] = alloca i32, align
149+
// CHECK-32-NEXT: [[X:%.*]] = alloca i32, align
150+
// CHECK-32-NEXT: [[Y:%.*]] = alloca i32, align
151+
// CHECK-32-NEXT: store i32 [[N]], ptr [[N_ADDR]], align
152+
// CHECK-32-NEXT: store i32 7, ptr [[X]], align
153+
// CHECK-32-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align
154+
// CHECK-32-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1
155+
// CHECK-32-NEXT: store i32 [[INC]], ptr [[N_ADDR]], align
156+
// CHECK-32-NEXT: store i32 [[TMP0]], ptr [[Y]], align
157+
// CHECK-32-NEXT: ret void
158+
//
159+
void test4(int n) {
160+
// n should not be evaluated in this case because the operator does not need
161+
// to evaluate it to know the result is 7.
162+
int x = _Countof(int[7][n++]);
163+
// n should be evaluated in this case, however.
164+
int y = _Countof(int[n++][7]);
165+
}
166+

0 commit comments

Comments
 (0)