xref: /llvm-project/llvm/test/Transforms/BDCE/binops-multiuse.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes=bdce < %s | FileCheck %s
3
4define void @or(i64 %a) {
5; CHECK-LABEL: define void @or(
6; CHECK-SAME: i64 [[A:%.*]]) {
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[A]], 8
9; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[A]], 16
10; CHECK-NEXT:    call void @use(i64 [[RET1]])
11; CHECK-NEXT:    call void @use(i64 [[RET2]])
12; CHECK-NEXT:    ret void
13;
14entry:
15  %or = or i64 %a, 3                              ; Mask:          0000 0011
16  %ret1 = and i64 %or, 8                          ; Demanded bits: 0000 1000
17  %ret2 = and i64 %or, 16                         ; Demanded bits: 0001 0000
18  call void @use(i64 %ret1)
19  call void @use(i64 %ret2)
20  ret void
21}
22
23define void @xor(i64 %a) {
24; CHECK-LABEL: define void @xor(
25; CHECK-SAME: i64 [[A:%.*]]) {
26; CHECK-NEXT:  entry:
27; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[A]], 8
28; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[A]], 16
29; CHECK-NEXT:    call void @use(i64 [[RET1]])
30; CHECK-NEXT:    call void @use(i64 [[RET2]])
31; CHECK-NEXT:    ret void
32;
33entry:
34  %xor = xor i64 %a, 3                            ; Mask:          0000 0011
35  %ret1 = and i64 %xor, 8                         ; Demanded bits: 0000 1000
36  %ret2 = and i64 %xor, 16                        ; Demanded bits: 0001 0000
37  call void @use(i64 %ret1)
38  call void @use(i64 %ret2)
39  ret void
40}
41
42define void @and(i64 %a) {
43; CHECK-LABEL: define void @and(
44; CHECK-SAME: i64 [[A:%.*]]) {
45; CHECK-NEXT:  entry:
46; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[A]], 8
47; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[A]], 16
48; CHECK-NEXT:    call void @use(i64 [[RET1]])
49; CHECK-NEXT:    call void @use(i64 [[RET2]])
50; CHECK-NEXT:    ret void
51;
52entry:
53  %and = and i64 %a, 24                           ; Mask:          0001 1000
54  %ret1 = and i64 %and, 8                         ; Demanded bits: 0000 1000
55  %ret2 = and i64 %and, 16                        ; Demanded bits: 0001 0000
56  call void @use(i64 %ret1)
57  call void @use(i64 %ret2)
58  ret void
59}
60
61define void @or_of_and(i64 %a, i64 %b) {
62; CHECK-LABEL: define void @or_of_and(
63; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
64; CHECK-NEXT:  entry:
65; CHECK-NEXT:    [[OR:%.*]] = or i64 [[A]], [[B]]
66; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[OR]], 8
67; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[OR]], 16
68; CHECK-NEXT:    call void @use(i64 [[RET1]])
69; CHECK-NEXT:    call void @use(i64 [[RET2]])
70; CHECK-NEXT:    ret void
71;
72entry:
73  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
74  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
75  %or = or i64 %and1, %and2
76  %ret1 = and i64 %or, 8                          ; Demanded bits: 0000 1000
77  %ret2 = and i64 %or, 16                         ; Demanded bits: 0001 0000
78  call void @use(i64 %ret1)
79  call void @use(i64 %ret2)
80  ret void
81}
82
83define void @or_disjoint_of_and(i64 %a, i64 %b) {
84; CHECK-LABEL: define void @or_disjoint_of_and(
85; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
86; CHECK-NEXT:  entry:
87; CHECK-NEXT:    [[OR:%.*]] = or i64 [[A]], [[B]]
88; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[OR]], 8
89; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[OR]], 16
90; CHECK-NEXT:    call void @use(i64 [[RET1]])
91; CHECK-NEXT:    call void @use(i64 [[RET2]])
92; CHECK-NEXT:    ret void
93;
94entry:
95  %and1 = and i64 %a, 56                          ; Mask:          0011 1000
96  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
97  %or = or disjoint i64 %and1, %and2
98  %ret1 = and i64 %or, 8                          ; Demanded bits: 0000 1000
99  %ret2 = and i64 %or, 16                         ; Demanded bits: 0001 0000
100  call void @use(i64 %ret1)
101  call void @use(i64 %ret2)
102  ret void
103}
104
105define void @select_of_and(i1 %c, i64 %a, i64 %b) {
106; CHECK-LABEL: define void @select_of_and(
107; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
108; CHECK-NEXT:  entry:
109; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]]
110; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
111; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
112; CHECK-NEXT:    call void @use(i64 [[RET1]])
113; CHECK-NEXT:    call void @use(i64 [[RET2]])
114; CHECK-NEXT:    ret void
115;
116entry:
117  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
118  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
119  %s = select i1 %c, i64 %and1, i64 %and2
120  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
121  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
122  call void @use(i64 %ret1)
123  call void @use(i64 %ret2)
124  ret void
125}
126
127define void @select_of_and_2(i1 %c, i64 %a, i64 %b) {
128; CHECK-LABEL: define void @select_of_and_2(
129; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
130; CHECK-NEXT:  entry:
131; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[B]], 23
132; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[AND2]]
133; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
134; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
135; CHECK-NEXT:    call void @use(i64 [[RET1]])
136; CHECK-NEXT:    call void @use(i64 [[RET2]])
137; CHECK-NEXT:    ret void
138;
139entry:
140  %and1 = and i64 %a, 25                          ; Mask:          0001 1001
141  %and2 = and i64 %b, 23                          ; Mask:          0001 0111
142  %s = select i1 %c, i64 %and1, i64 %and2
143  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
144  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
145  call void @use(i64 %ret1)
146  call void @use(i64 %ret2)
147  ret void
148}
149
150define void @select_of_and_multiuse(i1 %c, i64 %a, i64 %b) {
151; CHECK-LABEL: define void @select_of_and_multiuse(
152; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
153; CHECK-NEXT:  entry:
154; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[B]], 25
155; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[AND2]]
156; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
157; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
158; CHECK-NEXT:    call void @use(i64 [[RET1]])
159; CHECK-NEXT:    call void @use2(i64 [[RET2]], i64 [[AND2]])
160; CHECK-NEXT:    ret void
161;
162entry:
163  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
164  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
165  %s = select i1 %c, i64 %and1, i64 %and2
166  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
167  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
168  call void @use(i64 %ret1)
169  call void @use2(i64 %ret2, i64 %and2)
170  ret void
171}
172
173define void @select_of_and_different_demanded(i1 %c, i64 %a, i64 %b) {
174; CHECK-LABEL: define void @select_of_and_different_demanded(
175; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
176; CHECK-NEXT:  entry:
177; CHECK-NEXT:    [[AND1:%.*]] = and i64 0, 24
178; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[B]], 25
179; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[AND1]], i64 [[AND2]]
180; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 3
181; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 7
182; CHECK-NEXT:    call void @use(i64 [[RET1]])
183; CHECK-NEXT:    call void @use(i64 [[RET2]])
184; CHECK-NEXT:    ret void
185;
186entry:
187  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
188  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
189  %s = select i1 %c, i64 %and1, i64 %and2
190  %ret1 = and i64 %s, 3                           ; Demanded bits: 0000 0011
191  %ret2 = and i64 %s, 7                           ; Demanded bits: 0000 0111
192  call void @use(i64 %ret1)
193  call void @use(i64 %ret2)
194  ret void
195}
196
197define void @select_of_or(i1 %c, i64 %a, i64 %b) {
198; CHECK-LABEL: define void @select_of_or(
199; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
200; CHECK-NEXT:  entry:
201; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]]
202; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
203; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
204; CHECK-NEXT:    call void @use(i64 [[RET1]])
205; CHECK-NEXT:    call void @use(i64 [[RET2]])
206; CHECK-NEXT:    ret void
207;
208entry:
209  %or1 = or i64 %a, 3                             ; Mask:          0000 0011
210  %or2 = or i64 %b, 192                           ; Mask:          1100 0000
211  %s = select i1 %c, i64 %or1, i64 %or2
212  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
213  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
214  call void @use(i64 %ret1)
215  call void @use(i64 %ret2)
216  ret void
217}
218
219define void @select_of_xor(i1 %c, i64 %a, i64 %b) {
220; CHECK-LABEL: define void @select_of_xor(
221; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
222; CHECK-NEXT:  entry:
223; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]]
224; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
225; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
226; CHECK-NEXT:    call void @use(i64 [[RET1]])
227; CHECK-NEXT:    call void @use(i64 [[RET2]])
228; CHECK-NEXT:    ret void
229;
230entry:
231  %xor1 = xor i64 %a, 128                         ; Mask:          1000 0000
232  %xor2 = xor i64 %b, 36                          ; Mask:          0010 0100
233  %s = select i1 %c, i64 %xor1, i64 %xor2
234  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
235  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
236  call void @use(i64 %ret1)
237  call void @use(i64 %ret2)
238  ret void
239}
240
241define void @select_vectorized(i1 %c, <2 x i8> %a, <2 x i8> %b) {
242; CHECK-LABEL: define void @select_vectorized(
243; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
244; CHECK-NEXT:  entry:
245; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], <2 x i8> [[A]], <2 x i8> [[B]]
246; CHECK-NEXT:    [[RET1:%.*]] = and <2 x i8> [[S]], splat (i8 4)
247; CHECK-NEXT:    [[RET2:%.*]] = and <2 x i8> [[S]], splat (i8 12)
248; CHECK-NEXT:    call void @use3(<2 x i8> [[RET1]])
249; CHECK-NEXT:    call void @use3(<2 x i8> [[RET2]])
250; CHECK-NEXT:    ret void
251;
252entry:
253  %and1 = and <2 x i8> %a, <i8 28, i8 28>
254  %and2 = and <2 x i8> %b, <i8 29, i8 29>
255  %s = select i1 %c, <2 x i8> %and1, <2 x i8> %and2
256  %ret1 = and <2 x i8> %s, <i8 4, i8 4>
257  %ret2 = and <2 x i8> %s, <i8 12, i8 12>
258  call void @use3(<2 x i8> %ret1)
259  call void @use3(<2 x i8> %ret2)
260  ret void
261}
262
263declare void @use(i64)
264declare void @use2(i64, i64)
265declare void @use3(<2 x i8>)
266