xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/bitfield.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
2f4a2713aSLionel Sambuc // RUN:   | FileCheck -check-prefix=CHECK-X86-64 %s
3f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm -o - %s \
4f4a2713aSLionel Sambuc // RUN:   | FileCheck -check-prefix=CHECK-PPC64 %s
5f4a2713aSLionel Sambuc //
6f4a2713aSLionel Sambuc // Tests for bitfield access patterns in C++ with special attention to
7f4a2713aSLionel Sambuc // conformance to C++11 memory model requirements.
8f4a2713aSLionel Sambuc 
9f4a2713aSLionel Sambuc namespace N0 {
10f4a2713aSLionel Sambuc   // Test basic bitfield layout access across interesting byte and word
11f4a2713aSLionel Sambuc   // boundaries on both little endian and big endian platforms.
12f4a2713aSLionel Sambuc   struct __attribute__((packed)) S {
13f4a2713aSLionel Sambuc     unsigned b00 : 14;
14f4a2713aSLionel Sambuc     unsigned b01 : 2;
15f4a2713aSLionel Sambuc     unsigned b20 : 6;
16f4a2713aSLionel Sambuc     unsigned b21 : 2;
17f4a2713aSLionel Sambuc     unsigned b30 : 30;
18f4a2713aSLionel Sambuc     unsigned b31 : 2;
19f4a2713aSLionel Sambuc     unsigned b70 : 6;
20f4a2713aSLionel Sambuc     unsigned b71 : 2;
21f4a2713aSLionel Sambuc   };
read00(S * s)22f4a2713aSLionel Sambuc   unsigned read00(S* s) {
23f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read00
24f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
25f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
26f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[val]], 16383
27f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
28f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
29f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read00
30f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
31f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
32f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 50
33f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[shr]] to i32
34f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
35f4a2713aSLionel Sambuc     return s->b00;
36f4a2713aSLionel Sambuc   }
read01(S * s)37f4a2713aSLionel Sambuc   unsigned read01(S* s) {
38f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read01
39f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
40f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
41f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 14
42f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 3
43f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
44f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
45f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read01
46f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
47f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
48f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 48
49f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 3
50f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
51f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
52f4a2713aSLionel Sambuc     return s->b01;
53f4a2713aSLionel Sambuc   }
read20(S * s)54f4a2713aSLionel Sambuc   unsigned read20(S* s) {
55f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read20
56f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
57f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
58f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 16
59f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 63
60f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
61f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
62f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read20
63f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
64f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
65f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 42
66f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 63
67f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
68f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
69f4a2713aSLionel Sambuc     return s->b20;
70f4a2713aSLionel Sambuc   }
read21(S * s)71f4a2713aSLionel Sambuc   unsigned read21(S* s) {
72f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read21
73f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
74f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
75f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 22
76f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 3
77f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
78f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
79f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read21
80f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
81f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
82f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 40
83f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 3
84f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
85f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
86f4a2713aSLionel Sambuc     return s->b21;
87f4a2713aSLionel Sambuc   }
read30(S * s)88f4a2713aSLionel Sambuc   unsigned read30(S* s) {
89f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read30
90f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
91f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
92f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 24
93f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 1073741823
94f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
95f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
96f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read30
97f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
98f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
99f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 10
100f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 1073741823
101f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
102f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
103f4a2713aSLionel Sambuc     return s->b30;
104f4a2713aSLionel Sambuc   }
read31(S * s)105f4a2713aSLionel Sambuc   unsigned read31(S* s) {
106f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read31
107f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
108f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
109f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 54
110f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 3
111f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
112f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
113f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read31
114f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
115f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
116f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 8
117f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 3
118f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
119f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
120f4a2713aSLionel Sambuc     return s->b31;
121f4a2713aSLionel Sambuc   }
read70(S * s)122f4a2713aSLionel Sambuc   unsigned read70(S* s) {
123f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read70
124f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
125f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
126f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 56
127f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 63
128f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
129f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
130f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read70
131f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
132f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
133f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 2
134f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 63
135f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
136f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
137f4a2713aSLionel Sambuc     return s->b70;
138f4a2713aSLionel Sambuc   }
read71(S * s)139f4a2713aSLionel Sambuc   unsigned read71(S* s) {
140f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read71
141f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
142f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]]   = load i64* %[[ptr]]
143f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 62
144f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[shr]] to i32
145f4a2713aSLionel Sambuc     // CHECK-X86-64:                   ret i32 %[[trunc]]
146f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read71
147f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
148f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]]   = load i64* %[[ptr]]
149f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[val]], 3
150f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
151f4a2713aSLionel Sambuc     // CHECK-PPC64:                   ret i32 %[[trunc]]
152f4a2713aSLionel Sambuc     return s->b71;
153f4a2713aSLionel Sambuc   }
154f4a2713aSLionel Sambuc }
155f4a2713aSLionel Sambuc 
156f4a2713aSLionel Sambuc namespace N1 {
157f4a2713aSLionel Sambuc   // Ensure that neither loads nor stores to bitfields are not widened into
158f4a2713aSLionel Sambuc   // other memory locations. (PR13691)
159f4a2713aSLionel Sambuc   //
160f4a2713aSLionel Sambuc   // NOTE: We could potentially widen loads based on their alignment if we are
161f4a2713aSLionel Sambuc   // comfortable requiring that subsequent memory locations within the
162f4a2713aSLionel Sambuc   // alignment-widened load are not volatile.
163f4a2713aSLionel Sambuc   struct S {
164f4a2713aSLionel Sambuc     char a;
165f4a2713aSLionel Sambuc     unsigned b : 1;
166f4a2713aSLionel Sambuc     char c;
167f4a2713aSLionel Sambuc   };
read(S * s)168f4a2713aSLionel Sambuc   unsigned read(S* s) {
169f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N14read
170f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
171f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]] = load i8* %[[ptr]]
172f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]] = and i8 %[[val]], 1
173f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ext:.*]] = zext i8 %[[and]] to i32
174f4a2713aSLionel Sambuc     // CHECK-X86-64:                 ret i32 %[[ext]]
175f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N14read
176f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
177f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]] = load i8* %[[ptr]]
178f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]] = lshr i8 %[[val]], 7
179f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ext:.*]] = zext i8 %[[shr]] to i32
180f4a2713aSLionel Sambuc     // CHECK-PPC64:                 ret i32 %[[ext]]
181f4a2713aSLionel Sambuc     return s->b;
182f4a2713aSLionel Sambuc   }
write(S * s,unsigned x)183f4a2713aSLionel Sambuc   void write(S* s, unsigned x) {
184f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N15write
185f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]     = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
186f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[x_trunc:.*]] = trunc i32 %{{.*}} to i8
187f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old:.*]]     = load i8* %[[ptr]]
188f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[x_and:.*]]   = and i8 %[[x_trunc]], 1
189f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old_and:.*]] = and i8 %[[old]], -2
190f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new:.*]]     = or i8 %[[old_and]], %[[x_and]]
191f4a2713aSLionel Sambuc     // CHECK-X86-64:                     store i8 %[[new]], i8* %[[ptr]]
192f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N15write
193f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]     = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
194f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_trunc:.*]] = trunc i32 %{{.*}} to i8
195f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old:.*]]     = load i8* %[[ptr]]
196f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_and:.*]]   = and i8 %[[x_trunc]], 1
197f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i8 %[[x_and]], 7
198f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old_and:.*]] = and i8 %[[old]], 127
199f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new:.*]]     = or i8 %[[old_and]], %[[x_shl]]
200f4a2713aSLionel Sambuc     // CHECK-PPC64:                     store i8 %[[new]], i8* %[[ptr]]
201f4a2713aSLionel Sambuc     s->b = x;
202f4a2713aSLionel Sambuc   }
203f4a2713aSLionel Sambuc }
204f4a2713aSLionel Sambuc 
205f4a2713aSLionel Sambuc namespace N2 {
206f4a2713aSLionel Sambuc   // Do widen loads and stores to bitfields when those bitfields have padding
207f4a2713aSLionel Sambuc   // within the struct following them.
208f4a2713aSLionel Sambuc   struct S {
209f4a2713aSLionel Sambuc     unsigned b : 24;
210f4a2713aSLionel Sambuc     void *p;
211f4a2713aSLionel Sambuc   };
read(S * s)212f4a2713aSLionel Sambuc   unsigned read(S* s) {
213f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N24read
214f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
215f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]] = load i32* %[[ptr]]
216f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]] = and i32 %[[val]], 16777215
217f4a2713aSLionel Sambuc     // CHECK-X86-64:                 ret i32 %[[and]]
218f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N24read
219f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
220f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]] = load i32* %[[ptr]]
221f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]] = lshr i32 %[[val]], 8
222f4a2713aSLionel Sambuc     // CHECK-PPC64:                 ret i32 %[[shr]]
223f4a2713aSLionel Sambuc     return s->b;
224f4a2713aSLionel Sambuc   }
write(S * s,unsigned x)225f4a2713aSLionel Sambuc   void write(S* s, unsigned x) {
226f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N25write
227f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
228f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old:.*]]     = load i32* %[[ptr]]
229f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
230f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old_and:.*]] = and i32 %[[old]], -16777216
231f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_and]]
232f4a2713aSLionel Sambuc     // CHECK-X86-64:                     store i32 %[[new]], i32* %[[ptr]]
233f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N25write
234f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
235f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old:.*]]     = load i32* %[[ptr]]
236f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
237f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i32 %[[x_and]], 8
238f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old_and:.*]] = and i32 %[[old]], 255
239f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_shl]]
240f4a2713aSLionel Sambuc     // CHECK-PPC64:                     store i32 %[[new]], i32* %[[ptr]]
241f4a2713aSLionel Sambuc     s->b = x;
242f4a2713aSLionel Sambuc   }
243f4a2713aSLionel Sambuc }
244f4a2713aSLionel Sambuc 
245f4a2713aSLionel Sambuc namespace N3 {
246f4a2713aSLionel Sambuc   // Do widen loads and stores to bitfields through the trailing padding at the
247f4a2713aSLionel Sambuc   // end of a struct.
248f4a2713aSLionel Sambuc   struct S {
249f4a2713aSLionel Sambuc     unsigned b : 24;
250f4a2713aSLionel Sambuc   };
read(S * s)251f4a2713aSLionel Sambuc   unsigned read(S* s) {
252f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N34read
253f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
254f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]] = load i32* %[[ptr]]
255f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]] = and i32 %[[val]], 16777215
256f4a2713aSLionel Sambuc     // CHECK-X86-64:                 ret i32 %[[and]]
257f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N34read
258f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
259f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]] = load i32* %[[ptr]]
260f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]] = lshr i32 %[[val]], 8
261f4a2713aSLionel Sambuc     // CHECK-PPC64:                 ret i32 %[[shr]]
262f4a2713aSLionel Sambuc     return s->b;
263f4a2713aSLionel Sambuc   }
write(S * s,unsigned x)264f4a2713aSLionel Sambuc   void write(S* s, unsigned x) {
265f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N35write
266f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
267f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old:.*]]     = load i32* %[[ptr]]
268f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
269f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old_and:.*]] = and i32 %[[old]], -16777216
270f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_and]]
271f4a2713aSLionel Sambuc     // CHECK-X86-64:                     store i32 %[[new]], i32* %[[ptr]]
272f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N35write
273f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
274f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old:.*]]     = load i32* %[[ptr]]
275f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
276f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i32 %[[x_and]], 8
277f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old_and:.*]] = and i32 %[[old]], 255
278f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_shl]]
279f4a2713aSLionel Sambuc     // CHECK-PPC64:                     store i32 %[[new]], i32* %[[ptr]]
280f4a2713aSLionel Sambuc     s->b = x;
281f4a2713aSLionel Sambuc   }
282f4a2713aSLionel Sambuc }
283f4a2713aSLionel Sambuc 
284f4a2713aSLionel Sambuc namespace N4 {
285f4a2713aSLionel Sambuc   // Do NOT widen loads and stores to bitfields into padding at the end of
286f4a2713aSLionel Sambuc   // a class which might end up with members inside of it when inside a derived
287f4a2713aSLionel Sambuc   // class.
288f4a2713aSLionel Sambuc   struct Base {
~BaseN4::Base289f4a2713aSLionel Sambuc     virtual ~Base() {}
290f4a2713aSLionel Sambuc 
291f4a2713aSLionel Sambuc     unsigned b : 24;
292f4a2713aSLionel Sambuc   };
293f4a2713aSLionel Sambuc   // Imagine some other translation unit introduces:
294f4a2713aSLionel Sambuc #if 0
295f4a2713aSLionel Sambuc   struct Derived : public Base {
296f4a2713aSLionel Sambuc     char c;
297f4a2713aSLionel Sambuc   };
298f4a2713aSLionel Sambuc #endif
read(Base * s)299f4a2713aSLionel Sambuc   unsigned read(Base* s) {
300f4a2713aSLionel Sambuc     // FIXME: We should widen this load as long as the function isn't being
301*0a6a1f1dSLionel Sambuc     // instrumented by ThreadSanitizer.
302f4a2713aSLionel Sambuc     //
303f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N44read
304f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
305f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
306f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]] = load i24* %[[ptr]]
307f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ext:.*]] = zext i24 %[[val]] to i32
308f4a2713aSLionel Sambuc     // CHECK-X86-64:                 ret i32 %[[ext]]
309f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N44read
310f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
311f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
312f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]] = load i24* %[[ptr]]
313f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ext:.*]] = zext i24 %[[val]] to i32
314f4a2713aSLionel Sambuc     // CHECK-PPC64:                 ret i32 %[[ext]]
315f4a2713aSLionel Sambuc     return s->b;
316f4a2713aSLionel Sambuc   }
write(Base * s,unsigned x)317f4a2713aSLionel Sambuc   void write(Base* s, unsigned x) {
318f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N45write
319f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
320f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
321f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
322f4a2713aSLionel Sambuc     // CHECK-X86-64:                 store i24 %[[new]], i24* %[[ptr]]
323f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N45write
324f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
325f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
326f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
327f4a2713aSLionel Sambuc     // CHECK-PPC64:                 store i24 %[[new]], i24* %[[ptr]]
328f4a2713aSLionel Sambuc     s->b = x;
329f4a2713aSLionel Sambuc   }
330f4a2713aSLionel Sambuc }
331f4a2713aSLionel Sambuc 
332f4a2713aSLionel Sambuc namespace N5 {
333f4a2713aSLionel Sambuc   // Widen through padding at the end of a struct even if that struct
334f4a2713aSLionel Sambuc   // participates in a union with another struct which has a separate field in
335f4a2713aSLionel Sambuc   // that location. The reasoning is that if the operation is storing to that
336f4a2713aSLionel Sambuc   // member of the union, it must be the active member, and thus we can write
337f4a2713aSLionel Sambuc   // through the padding. If it is a load, it might be a load of a common
338f4a2713aSLionel Sambuc   // prefix through a non-active member, but in such a case the extra bits
339f4a2713aSLionel Sambuc   // loaded are masked off anyways.
340f4a2713aSLionel Sambuc   union U {
341f4a2713aSLionel Sambuc     struct X { unsigned b : 24; char c; } x;
342f4a2713aSLionel Sambuc     struct Y { unsigned b : 24; } y;
343f4a2713aSLionel Sambuc   };
read(U * u)344f4a2713aSLionel Sambuc   unsigned read(U* u) {
345f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N54read
346f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
347f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]] = load i32* %[[ptr]]
348f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[and:.*]] = and i32 %[[val]], 16777215
349f4a2713aSLionel Sambuc     // CHECK-X86-64:                 ret i32 %[[and]]
350f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N54read
351f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
352f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]] = load i32* %[[ptr]]
353f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[shr:.*]] = lshr i32 %[[val]], 8
354f4a2713aSLionel Sambuc     // CHECK-PPC64:                 ret i32 %[[shr]]
355f4a2713aSLionel Sambuc     return u->y.b;
356f4a2713aSLionel Sambuc   }
write(U * u,unsigned x)357f4a2713aSLionel Sambuc   void write(U* u, unsigned x) {
358f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N55write
359f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
360f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old:.*]]     = load i32* %[[ptr]]
361f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
362f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[old_and:.*]] = and i32 %[[old]], -16777216
363f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_and]]
364f4a2713aSLionel Sambuc     // CHECK-X86-64:                     store i32 %[[new]], i32* %[[ptr]]
365f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N55write
366f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
367f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old:.*]]     = load i32* %[[ptr]]
368f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
369f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i32 %[[x_and]], 8
370f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[old_and:.*]] = and i32 %[[old]], 255
371f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_shl]]
372f4a2713aSLionel Sambuc     // CHECK-PPC64:                     store i32 %[[new]], i32* %[[ptr]]
373f4a2713aSLionel Sambuc     u->y.b = x;
374f4a2713aSLionel Sambuc   }
375f4a2713aSLionel Sambuc }
376f4a2713aSLionel Sambuc 
377f4a2713aSLionel Sambuc namespace N6 {
378f4a2713aSLionel Sambuc   // Zero-length bitfields partition the memory locations of bitfields for the
379f4a2713aSLionel Sambuc   // purposes of the memory model. That means stores must not span zero-length
380f4a2713aSLionel Sambuc   // bitfields and loads may only span them when we are not instrumenting with
381*0a6a1f1dSLionel Sambuc   // ThreadSanitizer.
382*0a6a1f1dSLionel Sambuc   // FIXME: We currently don't widen loads even without ThreadSanitizer, even
383f4a2713aSLionel Sambuc   // though we could.
384f4a2713aSLionel Sambuc   struct S {
385f4a2713aSLionel Sambuc     unsigned b1 : 24;
386f4a2713aSLionel Sambuc     unsigned char : 0;
387f4a2713aSLionel Sambuc     unsigned char b2 : 8;
388f4a2713aSLionel Sambuc   };
read(S * s)389f4a2713aSLionel Sambuc   unsigned read(S* s) {
390f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N64read
391f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
392f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val1:.*]] = load i24* %[[ptr1]]
393f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ext1:.*]] = zext i24 %[[val1]] to i32
394f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
395f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[val2:.*]] = load i8* %[[ptr2]]
396f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ext2:.*]] = zext i8 %[[val2]] to i32
397f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[add:.*]]  = add nsw i32 %[[ext1]], %[[ext2]]
398f4a2713aSLionel Sambuc     // CHECK-X86-64:                  ret i32 %[[add]]
399f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N64read
400f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
401f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val1:.*]] = load i24* %[[ptr1]]
402f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ext1:.*]] = zext i24 %[[val1]] to i32
403f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
404f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[val2:.*]] = load i8* %[[ptr2]]
405f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ext2:.*]] = zext i8 %[[val2]] to i32
406f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[add:.*]]  = add nsw i32 %[[ext1]], %[[ext2]]
407f4a2713aSLionel Sambuc     // CHECK-PPC64:                  ret i32 %[[add]]
408f4a2713aSLionel Sambuc     return s->b1 + s->b2;
409f4a2713aSLionel Sambuc   }
write(S * s,unsigned x)410f4a2713aSLionel Sambuc   void write(S* s, unsigned x) {
411f4a2713aSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N65write
412f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
413f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new1:.*]] = trunc i32 %{{.*}} to i24
414f4a2713aSLionel Sambuc     // CHECK-X86-64:                  store i24 %[[new1]], i24* %[[ptr1]]
415f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[new2:.*]] = trunc i32 %{{.*}} to i8
416f4a2713aSLionel Sambuc     // CHECK-X86-64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
417f4a2713aSLionel Sambuc     // CHECK-X86-64:                  store i8 %[[new2]], i8* %[[ptr2]]
418f4a2713aSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N65write
419f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
420f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new1:.*]] = trunc i32 %{{.*}} to i24
421f4a2713aSLionel Sambuc     // CHECK-PPC64:                  store i24 %[[new1]], i24* %[[ptr1]]
422f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[new2:.*]] = trunc i32 %{{.*}} to i8
423f4a2713aSLionel Sambuc     // CHECK-PPC64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
424f4a2713aSLionel Sambuc     // CHECK-PPC64:                  store i8 %[[new2]], i8* %[[ptr2]]
425f4a2713aSLionel Sambuc     s->b1 = x;
426f4a2713aSLionel Sambuc     s->b2 = x;
427f4a2713aSLionel Sambuc   }
428f4a2713aSLionel Sambuc }
429*0a6a1f1dSLionel Sambuc 
430*0a6a1f1dSLionel Sambuc namespace N7 {
431*0a6a1f1dSLionel Sambuc   // Similar to N4 except that this adds a virtual base to the picture. (PR18430)
432*0a6a1f1dSLionel Sambuc   // Do NOT widen loads and stores to bitfields into padding at the end of
433*0a6a1f1dSLionel Sambuc   // a class which might end up with members inside of it when inside a derived
434*0a6a1f1dSLionel Sambuc   // class.
435*0a6a1f1dSLionel Sambuc   struct B1 {
436*0a6a1f1dSLionel Sambuc     virtual void f();
437*0a6a1f1dSLionel Sambuc     unsigned b1 : 24;
438*0a6a1f1dSLionel Sambuc   };
439*0a6a1f1dSLionel Sambuc   struct B2 : virtual B1 {
440*0a6a1f1dSLionel Sambuc     virtual ~B2();
441*0a6a1f1dSLionel Sambuc     unsigned b : 24;
442*0a6a1f1dSLionel Sambuc   };
443*0a6a1f1dSLionel Sambuc   // Imagine some other translation unit introduces:
444*0a6a1f1dSLionel Sambuc #if 0
445*0a6a1f1dSLionel Sambuc   struct Derived : public B2 {
446*0a6a1f1dSLionel Sambuc     char c;
447*0a6a1f1dSLionel Sambuc   };
448*0a6a1f1dSLionel Sambuc #endif
read(B2 * s)449*0a6a1f1dSLionel Sambuc   unsigned read(B2* s) {
450*0a6a1f1dSLionel Sambuc     // FIXME: We should widen this load as long as the function isn't being
451*0a6a1f1dSLionel Sambuc     // instrumented by ThreadSanitizer.
452*0a6a1f1dSLionel Sambuc     //
453*0a6a1f1dSLionel Sambuc     // CHECK-X86-64-LABEL: define i32 @_ZN2N74read
454*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
455*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
456*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[val:.*]] = load i24* %[[ptr]]
457*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[ext:.*]] = zext i24 %[[val]] to i32
458*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:                 ret i32 %[[ext]]
459*0a6a1f1dSLionel Sambuc     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N74read
460*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
461*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
462*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[val:.*]] = load i24* %[[ptr]]
463*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[ext:.*]] = zext i24 %[[val]] to i32
464*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:                 ret i32 %[[ext]]
465*0a6a1f1dSLionel Sambuc     return s->b;
466*0a6a1f1dSLionel Sambuc   }
write(B2 * s,unsigned x)467*0a6a1f1dSLionel Sambuc   void write(B2* s, unsigned x) {
468*0a6a1f1dSLionel Sambuc     // CHECK-X86-64-LABEL: define void @_ZN2N75write
469*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
470*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
471*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
472*0a6a1f1dSLionel Sambuc     // CHECK-X86-64:                 store i24 %[[new]], i24* %[[ptr]]
473*0a6a1f1dSLionel Sambuc     // CHECK-PPC64-LABEL: define void @_ZN2N75write
474*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
475*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
476*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
477*0a6a1f1dSLionel Sambuc     // CHECK-PPC64:                 store i24 %[[new]], i24* %[[ptr]]
478*0a6a1f1dSLionel Sambuc     s->b = x;
479*0a6a1f1dSLionel Sambuc   }
480*0a6a1f1dSLionel Sambuc }
481