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