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