xref: /llvm-project/clang/test/CodeGenCXX/finegrain-bitfield-access.cpp (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \
2 // RUN:   -emit-llvm -o - %s | FileCheck %s
3 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \
4 // RUN:   -emit-llvm -fsanitize=address -o - %s | FileCheck %s --check-prefix=SANITIZE
5 // Check -fsplit-bitfields will be ignored since sanitizer is enabled.
6 
7 struct S1 {
8   unsigned f1:2;
9   unsigned f2:6;
10   unsigned f3:8;
11   unsigned f4:4;
12   unsigned f5:8;
13 };
14 
15 S1 a1;
16 unsigned read8_1() {
17   // CHECK-LABEL: @_Z7read8_1v
18   // CHECK: %bf.load = load i8, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 1), align 1
19   // CHECK-NEXT: %bf.cast = zext i8 %bf.load to i32
20   // CHECK-NEXT: ret i32 %bf.cast
21   // SANITIZE-LABEL: @_Z7read8_1v
22   // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 4
23   // SANITIZE: %bf.lshr = lshr i32 %bf.load, 8
24   // SANITIZE: %bf.clear = and i32 %bf.lshr, 255
25   // SANITIZE: ret i32 %bf.clear
26   return a1.f3;
27 }
28 void write8_1() {
29   // CHECK-LABEL: @_Z8write8_1v
30   // CHECK: store i8 3, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 1), align 1
31   // CHECK-NEXT: ret void
32   // SANITIZE-LABEL: @_Z8write8_1v
33   // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 4
34   // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -65281
35   // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 768
36   // SANITIZE-NEXT: store i32 %bf.set, ptr {{.*}}, align 4
37   // SANITIZE-NEXT: ret void
38   a1.f3 = 3;
39 }
40 
41 unsigned read8_2() {
42   // CHECK-LABEL: @_Z7read8_2v
43   // CHECK: %bf.load = load i16, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 2
44   // CHECK-NEXT: %bf.lshr = lshr i16 %bf.load, 4
45   // CHECK-NEXT: %bf.clear = and i16 %bf.lshr, 255
46   // CHECK-NEXT: %bf.cast = zext i16 %bf.clear to i32
47   // CHECK-NEXT: ret i32 %bf.cast
48   // SANITIZE-LABEL: @_Z7read8_2v
49   // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 4
50   // SANITIZE-NEXT: %bf.lshr = lshr i32 %bf.load, 20
51   // SANITIZE-NEXT: %bf.clear = and i32 %bf.lshr, 255
52   // SANITIZE-NEXT: ret i32 %bf.clear
53   return a1.f5;
54 }
55 void write8_2() {
56   // CHECK-LABEL: @_Z8write8_2v
57   // CHECK: %bf.load = load i16, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 2
58   // CHECK-NEXT: %bf.clear = and i16 %bf.load, -4081
59   // CHECK-NEXT: %bf.set = or i16 %bf.clear, 48
60   // CHECK-NEXT: store i16 %bf.set, ptr getelementptr inbounds nuw (%struct.S1, ptr @a1, i32 0, i32 2), align 2
61   // CHECK-NEXT: ret void
62   // SANITIZE-LABEL: @_Z8write8_2v
63   // SANITIZE: %bf.load = load i32, ptr {{.*}}, align 4
64   // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -267386881
65   // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 3145728
66   // SANITIZE-NEXT: store i32 %bf.set, ptr {{.*}}, align 4
67   // SANITIZE-NEXT: ret void
68   a1.f5 = 3;
69 }
70 
71 struct S2 {
72   unsigned long f1:16;
73   unsigned long f2:16;
74   unsigned long f3:6;
75 };
76 
77 S2 a2;
78 unsigned read16_1() {
79   // CHECK-LABEL: @_Z8read16_1v
80   // CHECK: %bf.load = load i16, ptr @a2, align 8
81   // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64
82   // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32
83   // CHECK-NEXT: ret i32 %conv
84   // SANITIZE-LABEL: @_Z8read16_1v
85   // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8
86   // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 65535
87   // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32
88   // SANITIZE-NEXT: ret i32 %conv
89   return a2.f1;
90 }
91 unsigned read16_2() {
92   // CHECK-LABEL: @_Z8read16_2v
93   // CHECK: %bf.load = load i16, ptr getelementptr inbounds nuw (%struct.S2, ptr @a2, i32 0, i32 1), align 2
94   // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64
95   // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32
96   // CHECK-NEXT: ret i32 %conv
97   // SANITIZE-LABEL: @_Z8read16_2v
98   // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8
99   // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 16
100   // SANITIZE-NEXT: %bf.clear = and i64 %bf.lshr, 65535
101   // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32
102   // SANITIZE-NEXT: ret i32 %conv
103   return a2.f2;
104 }
105 
106 void write16_1() {
107   // CHECK-LABEL: @_Z9write16_1v
108   // CHECK: store i16 5, ptr @a2, align 8
109   // CHECK-NEXT: ret void
110   // SANITIZE-LABEL: @_Z9write16_1v
111   // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8
112   // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -65536
113   // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 5
114   // SANITIZE-NEXT: store i64 %bf.set, ptr {{.*}}, align 8
115   // SANITIZE-NEXT: ret void
116   a2.f1 = 5;
117 }
118 void write16_2() {
119   // CHECK-LABEL: @_Z9write16_2v
120   // CHECK: store i16 5, ptr getelementptr inbounds nuw (%struct.S2, ptr @a2, i32 0, i32 1), align 2
121   // CHECK-NEXT: ret void
122   // SANITIZE-LABEL: @_Z9write16_2v
123   // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8
124   // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -4294901761
125   // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 327680
126   // SANITIZE-NEXT: store i64 %bf.set, ptr {{.*}}, align 8
127   // SANITIZE-NEXT: ret void
128   a2.f2 = 5;
129 }
130 
131 struct S3 {
132   unsigned long f1:14;
133   unsigned long f2:18;
134   unsigned long f3:32;
135 };
136 
137 S3 a3;
138 unsigned read32_1() {
139   // CHECK-LABEL: @_Z8read32_1v
140   // CHECK: %bf.load = load i32, ptr getelementptr inbounds nuw (%struct.S3, ptr @a3, i32 0, i32 1), align 4
141   // CHECK-NEXT: %bf.cast = zext i32 %bf.load to i64
142   // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32
143   // CHECK-NEXT: ret i32 %conv
144   // SANITIZE-LABEL: @_Z8read32_1v
145   // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8
146   // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 32
147   // SANITIZE-NEXT: %conv = trunc i64 %bf.lshr to i32
148   // SANITIZE-NEXT: ret i32 %conv
149   return a3.f3;
150 }
151 void write32_1() {
152   // CHECK-LABEL: @_Z9write32_1v
153   // CHECK: store i32 5, ptr getelementptr inbounds nuw (%struct.S3, ptr @a3, i32 0, i32 1), align 4
154   // CHECK-NEXT: ret void
155   // SANITIZE-LABEL: @_Z9write32_1v
156   // SANITIZE: %bf.load = load i64, ptr {{.*}}, align 8
157   // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 4294967295
158   // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 21474836480
159   // SANITIZE-NEXT: store i64 %bf.set, ptr {{.*}}, align 8
160   // SANITIZE-NEXT: ret void
161   a3.f3 = 5;
162 }
163