1; RUN: opt -S -mtriple=amdgcn-- -codegenprepare < %s | FileCheck -check-prefix=OPT %s
2; RUN: opt -S -mtriple=amdgcn-- -mcpu=tonga -codegenprepare < %s | FileCheck -check-prefix=OPT %s
3; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI %s
4; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
5
6; This particular case will actually be worse in terms of code size
7; from sinking into both.
8
9; OPT-LABEL: @sink_ubfe_i32(
10; OPT: entry:
11; OPT-NEXT: br i1
12
13; OPT: bb0:
14; OPT: %0 = lshr i32 %arg1, 8
15; OPT-NEXT: %val0 = and i32 %0, 255
16; OPT: br label
17
18; OPT: bb1:
19; OPT: %1 = lshr i32 %arg1, 8
20; OPT-NEXT: %val1 = and i32 %1, 127
21; OPT: br label
22
23; OPT: ret:
24; OPT: store
25; OPT: ret
26
27
28; GCN-LABEL: {{^}}sink_ubfe_i32:
29; GCN-NOT: lshr
30; GCN: s_cbranch_vccnz
31
32; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80008
33; GCN: BB0_2:
34; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70008
35
36; GCN: BB0_3:
37; GCN: buffer_store_dword
38; GCN: s_endpgm
39define void @sink_ubfe_i32(i32 addrspace(1)* %out, i32 %arg1) #0 {
40entry:
41  %shr = lshr i32 %arg1, 8
42  br i1 undef, label %bb0, label %bb1
43
44bb0:
45  %val0 = and i32 %shr, 255
46  store volatile i32 0, i32 addrspace(1)* undef
47  br label %ret
48
49bb1:
50  %val1 = and i32 %shr, 127
51  store volatile i32 0, i32 addrspace(1)* undef
52  br label %ret
53
54ret:
55  %phi = phi i32 [ %val0, %bb0 ], [ %val1, %bb1 ]
56  store i32 %phi, i32 addrspace(1)* %out
57  ret void
58}
59
60; OPT-LABEL: @sink_sbfe_i32(
61; OPT: entry:
62; OPT-NEXT: br i1
63
64; OPT: bb0:
65; OPT: %0 = ashr i32 %arg1, 8
66; OPT-NEXT: %val0 = and i32 %0, 255
67; OPT: br label
68
69; OPT: bb1:
70; OPT: %1 = ashr i32 %arg1, 8
71; OPT-NEXT: %val1 = and i32 %1, 127
72; OPT: br label
73
74; OPT: ret:
75; OPT: store
76; OPT: ret
77
78; GCN-LABEL: {{^}}sink_sbfe_i32:
79define void @sink_sbfe_i32(i32 addrspace(1)* %out, i32 %arg1) #0 {
80entry:
81  %shr = ashr i32 %arg1, 8
82  br i1 undef, label %bb0, label %bb1
83
84bb0:
85  %val0 = and i32 %shr, 255
86  store volatile i32 0, i32 addrspace(1)* undef
87  br label %ret
88
89bb1:
90  %val1 = and i32 %shr, 127
91  store volatile i32 0, i32 addrspace(1)* undef
92  br label %ret
93
94ret:
95  %phi = phi i32 [ %val0, %bb0 ], [ %val1, %bb1 ]
96  store i32 %phi, i32 addrspace(1)* %out
97  ret void
98}
99
100
101; OPT-LABEL: @sink_ubfe_i16(
102; OPT: entry:
103; OPT-NEXT: br i1
104
105; OPT: bb0:
106; OPT: %0 = lshr i16 %arg1, 4
107; OPT-NEXT: %val0 = and i16 %0, 255
108; OPT: br label
109
110; OPT: bb1:
111; OPT: %1 = lshr i16 %arg1, 4
112; OPT-NEXT: %val1 = and i16 %1, 127
113; OPT: br label
114
115; OPT: ret:
116; OPT: store
117; OPT: ret
118
119; For GFX8: since i16 is legal type, we cannot sink lshr into BBs.
120
121; GCN-LABEL: {{^}}sink_ubfe_i16:
122; GCN-NOT: lshr
123; VI: s_bfe_u32 s0, s0, 0xc0004
124; GCN: s_cbranch_vccnz
125
126; SI: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80004
127; VI: s_and_b32 s0, s0, 0xff
128
129; GCN: BB2_2:
130; SI: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70004
131; VI: s_and_b32 s0, s0, 0x7f
132
133; GCN: BB2_3:
134; GCN: buffer_store_short
135; GCN: s_endpgm
136define void @sink_ubfe_i16(i16 addrspace(1)* %out, i16 %arg1) #0 {
137entry:
138  %shr = lshr i16 %arg1, 4
139  br i1 undef, label %bb0, label %bb1
140
141bb0:
142  %val0 = and i16 %shr, 255
143  store volatile i16 0, i16 addrspace(1)* undef
144  br label %ret
145
146bb1:
147  %val1 = and i16 %shr, 127
148  store volatile i16 0, i16 addrspace(1)* undef
149  br label %ret
150
151ret:
152  %phi = phi i16 [ %val0, %bb0 ], [ %val1, %bb1 ]
153  store i16 %phi, i16 addrspace(1)* %out
154  ret void
155}
156
157; We don't really want to sink this one since it isn't reducible to a
158; 32-bit BFE on one half of the integer.
159
160; OPT-LABEL: @sink_ubfe_i64_span_midpoint(
161; OPT: entry:
162; OPT-NOT: lshr
163; OPT: br i1
164
165; OPT: bb0:
166; OPT: %0 = lshr i64 %arg1, 30
167; OPT-NEXT: %val0 = and i64 %0, 255
168
169; OPT: bb1:
170; OPT: %1 = lshr i64 %arg1, 30
171; OPT-NEXT: %val1 = and i64 %1, 127
172
173; OPT: ret:
174; OPT: store
175; OPT: ret
176
177; GCN-LABEL: {{^}}sink_ubfe_i64_span_midpoint:
178; GCN: s_lshr_b64 s{{\[}}[[LO:[0-9]+]]:{{[0-9]+}}], s{{\[[0-9]+:[0-9]+\]}}, 30
179; GCN: s_cbranch_vccnz BB3_2
180
181; GCN: s_and_b32 s{{[0-9]+}}, s[[LO]], 0xff
182
183; GCN: BB3_2:
184; GCN: s_and_b32 s{{[0-9]+}}, s[[LO]], 0x7f
185
186; GCN: BB3_3:
187; GCN: buffer_store_dwordx2
188define void @sink_ubfe_i64_span_midpoint(i64 addrspace(1)* %out, i64 %arg1) #0 {
189entry:
190  %shr = lshr i64 %arg1, 30
191  br i1 undef, label %bb0, label %bb1
192
193bb0:
194  %val0 = and i64 %shr, 255
195  store volatile i32 0, i32 addrspace(1)* undef
196  br label %ret
197
198bb1:
199  %val1 = and i64 %shr, 127
200  store volatile i32 0, i32 addrspace(1)* undef
201  br label %ret
202
203ret:
204  %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ]
205  store i64 %phi, i64 addrspace(1)* %out
206  ret void
207}
208
209; OPT-LABEL: @sink_ubfe_i64_low32(
210; OPT: entry:
211; OPT-NOT: lshr
212; OPT: br i1
213
214; OPT: bb0:
215; OPT: %0 = lshr i64 %arg1, 15
216; OPT-NEXT: %val0 = and i64 %0, 255
217
218; OPT: bb1:
219; OPT: %1 = lshr i64 %arg1, 15
220; OPT-NEXT: %val1 = and i64 %1, 127
221
222; OPT: ret:
223; OPT: store
224; OPT: ret
225
226; GCN-LABEL: {{^}}sink_ubfe_i64_low32:
227
228; GCN: s_cbranch_vccnz BB4_2
229
230; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x8000f
231
232; GCN: BB4_2:
233; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x7000f
234
235; GCN: BB4_3:
236; GCN: buffer_store_dwordx2
237define void @sink_ubfe_i64_low32(i64 addrspace(1)* %out, i64 %arg1) #0 {
238entry:
239  %shr = lshr i64 %arg1, 15
240  br i1 undef, label %bb0, label %bb1
241
242bb0:
243  %val0 = and i64 %shr, 255
244  store volatile i32 0, i32 addrspace(1)* undef
245  br label %ret
246
247bb1:
248  %val1 = and i64 %shr, 127
249  store volatile i32 0, i32 addrspace(1)* undef
250  br label %ret
251
252ret:
253  %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ]
254  store i64 %phi, i64 addrspace(1)* %out
255  ret void
256}
257
258; OPT-LABEL: @sink_ubfe_i64_high32(
259; OPT: entry:
260; OPT-NOT: lshr
261; OPT: br i1
262
263; OPT: bb0:
264; OPT: %0 = lshr i64 %arg1, 35
265; OPT-NEXT: %val0 = and i64 %0, 255
266
267; OPT: bb1:
268; OPT: %1 = lshr i64 %arg1, 35
269; OPT-NEXT: %val1 = and i64 %1, 127
270
271; OPT: ret:
272; OPT: store
273; OPT: ret
274
275; GCN-LABEL: {{^}}sink_ubfe_i64_high32:
276; GCN: s_cbranch_vccnz BB5_2
277; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80003
278
279; GCN: BB5_2:
280; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70003
281
282; GCN: BB5_3:
283; GCN: buffer_store_dwordx2
284define void @sink_ubfe_i64_high32(i64 addrspace(1)* %out, i64 %arg1) #0 {
285entry:
286  %shr = lshr i64 %arg1, 35
287  br i1 undef, label %bb0, label %bb1
288
289bb0:
290  %val0 = and i64 %shr, 255
291  store volatile i32 0, i32 addrspace(1)* undef
292  br label %ret
293
294bb1:
295  %val1 = and i64 %shr, 127
296  store volatile i32 0, i32 addrspace(1)* undef
297  br label %ret
298
299ret:
300  %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ]
301  store i64 %phi, i64 addrspace(1)* %out
302  ret void
303}
304
305attributes #0 = { nounwind }
306