blob: 2a1fe71f961b7f94f5c9264269114c77c8817809 [file] [log] [blame]
John McCall7f416cc2015-09-08 08:05:57 +00001// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s
2
3extern int int_source();
4extern void int_sink(int x);
5
6namespace test0 {
7 struct A {
8 int aField;
9 int bField;
10 };
11
12 struct B {
13 int onebit : 2;
14 int twobit : 6;
15 int intField;
16 };
17
18 struct __attribute__((packed, aligned(2))) C : A, B {
19 };
20
21 // These accesses should have alignment 4 because they're at offset 0
22 // in a reference with an assumed alignment of 4.
23 // CHECK-LABEL: @_ZN5test01aERNS_1BE
24 void a(B &b) {
25 // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev()
26 // CHECK: [[B_P:%.*]] = load [[B:%.*]]*, [[B]]**
27 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
28 // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
29 // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
30 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
31 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
32 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
33 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 4
34 b.onebit = int_source();
35
36 // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]**
37 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
38 // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
39 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
40 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
41 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
42 // CHECK: call void @_Z8int_sinki(i32 [[T2]])
43 int_sink(b.onebit);
44 }
45
46 // These accesses should have alignment 2 because they're at offset 8
47 // in a reference/pointer with an assumed alignment of 2.
48 // CHECK-LABEL: @_ZN5test01bERNS_1CE
49 void b(C &c) {
50 // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev()
51 // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]**
52 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
53 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
54 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
55 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
56 // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
57 // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
58 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
59 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
60 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
61 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
62 c.onebit = int_source();
63
64 // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]**
65 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
66 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
67 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
68 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
69 // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
70 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
71 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
72 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
73 // CHECK: call void @_Z8int_sinki(i32 [[T2]])
74 int_sink(c.onebit);
75 }
76
77 // CHECK-LABEL: @_ZN5test01cEPNS_1CE
78 void c(C *c) {
79 // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev()
80 // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]**
81 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
82 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
83 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
84 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
85 // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
86 // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
87 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
88 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
89 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
90 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
91 c->onebit = int_source();
92
93 // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]**
94 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
95 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
96 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]*
97 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
98 // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
99 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
100 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
101 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
102 // CHECK: call void @_Z8int_sinki(i32 [[T2]])
103 int_sink(c->onebit);
104 }
105
106 // These accesses should have alignment 2 because they're at offset 8
107 // in an alignment-2 variable.
108 // CHECK-LABEL: @_ZN5test01dEv
109 void d() {
110 // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 2
111 C c;
112
NAKAMURA Takumic88d2fa2015-09-08 09:31:04 +0000113 // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev()
John McCall7f416cc2015-09-08 08:05:57 +0000114 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
115 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
116 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
117 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
118 // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
119 // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
120 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
121 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
122 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
123 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
124 c.onebit = int_source();
125
126 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
127 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
128 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]*
129 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
130 // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2
131 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
132 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
133 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
134 // CHECK: call void @_Z8int_sinki(i32 [[T2]])
135 int_sink(c.onebit);
136 }
137
138 // These accesses should have alignment 8 because they're at offset 8
139 // in an alignment-16 variable.
140 // CHECK-LABEL: @_ZN5test01eEv
141 void e() {
142 // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 16
143 __attribute__((aligned(16))) C c;
144
John McCalle78e08a2015-09-08 09:33:33 +0000145 // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev()
John McCall7f416cc2015-09-08 08:05:57 +0000146 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
147 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
148 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]*
149 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
150 // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8
151 // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 8
152 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3
153 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4
154 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
155 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 8
156 c.onebit = int_source();
157
158 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
159 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8
160 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]*
161 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
162 // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 8
163 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6
164 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6
165 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32
166 // CHECK: call void @_Z8int_sinki(i32 [[T2]])
167 int_sink(c.onebit);
168 }
169}
170
171namespace test1 {
172 struct Array {
173 int elts[4];
174 };
175
176 struct A {
177 __attribute__((aligned(16))) Array aArray;
178 };
179
180 struct B : virtual A {
181 void *bPointer; // puts bArray at offset 16
182 Array bArray;
183 };
184
185 struct C : virtual A { // must be viable as primary base
186 // Non-empty, nv-size not a multiple of 16.
187 void *cPointer1;
188 void *cPointer2;
189 };
190
191 // Proof of concept that the non-virtual components of B do not have
192 // to be 16-byte-aligned.
193 struct D : C, B {};
194
195 // For the following tests, we want to assign into a variable whose
196 // alignment is high enough that it will absolutely not be the
197 // constraint on the memcpy alignment.
198 typedef __attribute__((aligned(64))) Array AlignedArray;
199
200 // CHECK-LABEL: @_ZN5test11aERNS_1AE
201 void a(A &a) {
202 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY:%.*]], align 64
203 // CHECK: [[A_P:%.*]] = load [[A:%.*]]*, [[A]]**
204 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0
205 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
206 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
207 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
208 AlignedArray result = a.aArray;
209 }
210
211 // CHECK-LABEL: @_ZN5test11bERNS_1BE
212 void b(B &b) {
213 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64
214 // CHECK: [[B_P:%.*]] = load [[B:%.*]]*, [[B]]**
215 // CHECK: [[VPTR_P:%.*]] = bitcast [[B]]* [[B_P]] to i8**
216 // CHECK: [[VPTR:%.*]] = load i8*, i8** [[VPTR_P]], align 8
217 // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 -24
218 // CHECK: [[OFFSET_P:%.*]] = bitcast i8* [[T0]] to i64*
219 // CHECK: [[OFFSET:%.*]] = load i64, i64* [[OFFSET_P]], align 8
220 // CHECK: [[T0:%.*]] = bitcast [[B]]* [[B_P]] to i8*
221 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]]
222 // CHECK: [[A_P:%.*]] = bitcast i8* [[T1]] to [[A]]*
223 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0
224 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
225 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
226 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
227 AlignedArray result = b.aArray;
228 }
229
230 // CHECK-LABEL: @_ZN5test11cERNS_1BE
231 void c(B &b) {
232 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64
233 // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]**
234 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
235 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
236 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
237 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false)
238 AlignedArray result = b.bArray;
239 }
240
241 // CHECK-LABEL: @_ZN5test11dEPNS_1BE
242 void d(B *b) {
243 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64
244 // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]**
245 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
246 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
247 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
248 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false)
249 AlignedArray result = b->bArray;
250 }
251
252 // CHECK-LABEL: @_ZN5test11eEv
253 void e() {
254 // CHECK: [[B_P:%.*]] = alloca [[B]], align 16
255 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64
256 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
257 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
258 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
259 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
260 B b;
261 AlignedArray result = b.bArray;
262 }
263
264 // CHECK-LABEL: @_ZN5test11fEv
265 void f() {
266 // TODO: we should devirtualize this derived-to-base conversion.
267 // CHECK: [[D_P:%.*]] = alloca [[D:%.*]], align 16
268 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64
269 // CHECK: [[VPTR_P:%.*]] = bitcast [[D]]* [[D_P]] to i8**
270 // CHECK: [[VPTR:%.*]] = load i8*, i8** [[VPTR_P]], align 16
271 // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 -24
272 // CHECK: [[OFFSET_P:%.*]] = bitcast i8* [[T0]] to i64*
273 // CHECK: [[OFFSET:%.*]] = load i64, i64* [[OFFSET_P]], align 8
274 // CHECK: [[T0:%.*]] = bitcast [[D]]* [[D_P]] to i8*
275 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]]
276 // CHECK: [[A_P:%.*]] = bitcast i8* [[T1]] to [[A]]*
277 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0
278 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
279 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
280 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false)
281 D d;
282 AlignedArray result = d.aArray;
283 }
284
285 // CHECK-LABEL: @_ZN5test11gEv
286 void g() {
287 // CHECK: [[D_P:%.*]] = alloca [[D]], align 16
288 // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64
289 // CHECK: [[T0:%.*]] = bitcast [[D]]* [[D_P]] to i8*
290 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 24
291 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]*
292 // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2
293 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8*
294 // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8*
295 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false)
296 D d;
297 AlignedArray result = d.bArray;
298 }
299}