1; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI -check-prefix=FUNC %s
2; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI -check-prefix=FUNC %s
3; RUN: llc -march=r600 -mcpu=cypress -verify-machineinstrs < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
4
5; FUNC-LABEL: {{^}}sext_in_reg_i1_i32:
6; GCN: s_load_dword [[ARG:s[0-9]+]],
7; GCN: s_bfe_i32 [[SEXTRACT:s[0-9]+]], [[ARG]], 0x10000
8; GCN: v_mov_b32_e32 [[EXTRACT:v[0-9]+]], [[SEXTRACT]]
9; GCN: buffer_store_dword [[EXTRACT]],
10
11; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]]
12; EG: LSHR * [[ADDR]]
13; EG: BFE_INT * [[RES]], {{.*}}, 0.0, 1
14define void @sext_in_reg_i1_i32(i32 addrspace(1)* %out, i32 %in) #0 {
15  %shl = shl i32 %in, 31
16  %sext = ashr i32 %shl, 31
17  store i32 %sext, i32 addrspace(1)* %out
18  ret void
19}
20
21; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i32:
22; GCN: s_add_i32 [[VAL:s[0-9]+]],
23; GCN: s_sext_i32_i8 [[EXTRACT:s[0-9]+]], [[VAL]]
24; GCN: v_mov_b32_e32 [[VEXTRACT:v[0-9]+]], [[EXTRACT]]
25; GCN: buffer_store_dword [[VEXTRACT]],
26
27; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]]
28; EG: ADD_INT
29; EG-NEXT: BFE_INT [[RES]], {{.*}}, 0.0, literal
30; EG-NEXT: LSHR * [[ADDR]]
31define void @sext_in_reg_i8_to_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 {
32  %c = add i32 %a, %b ; add to prevent folding into extload
33  %shl = shl i32 %c, 24
34  %ashr = ashr i32 %shl, 24
35  store i32 %ashr, i32 addrspace(1)* %out, align 4
36  ret void
37}
38
39; FUNC-LABEL: {{^}}sext_in_reg_i16_to_i32:
40; GCN: s_add_i32 [[VAL:s[0-9]+]],
41; GCN: s_sext_i32_i16 [[EXTRACT:s[0-9]+]], [[VAL]]
42; GCN: v_mov_b32_e32 [[VEXTRACT:v[0-9]+]], [[EXTRACT]]
43; GCN: buffer_store_dword [[VEXTRACT]],
44
45; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]]
46; EG: ADD_INT
47; EG-NEXT: BFE_INT [[RES]], {{.*}}, 0.0, literal
48; EG-NEXT: LSHR * [[ADDR]]
49define void @sext_in_reg_i16_to_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 {
50  %c = add i32 %a, %b ; add to prevent folding into extload
51  %shl = shl i32 %c, 16
52  %ashr = ashr i32 %shl, 16
53  store i32 %ashr, i32 addrspace(1)* %out, align 4
54  ret void
55}
56
57; FUNC-LABEL: {{^}}sext_in_reg_i8_to_v1i32:
58; GCN: s_add_i32 [[VAL:s[0-9]+]],
59; GCN: s_sext_i32_i8 [[EXTRACT:s[0-9]+]], [[VAL]]
60; GCN: v_mov_b32_e32 [[VEXTRACT:v[0-9]+]], [[EXTRACT]]
61; GCN: buffer_store_dword [[VEXTRACT]],
62
63; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]]
64; EG: ADD_INT
65; EG-NEXT: BFE_INT [[RES]], {{.*}}, 0.0, literal
66; EG-NEXT: LSHR * [[ADDR]]
67define void @sext_in_reg_i8_to_v1i32(<1 x i32> addrspace(1)* %out, <1 x i32> %a, <1 x i32> %b) #0 {
68  %c = add <1 x i32> %a, %b ; add to prevent folding into extload
69  %shl = shl <1 x i32> %c, <i32 24>
70  %ashr = ashr <1 x i32> %shl, <i32 24>
71  store <1 x i32> %ashr, <1 x i32> addrspace(1)* %out, align 4
72  ret void
73}
74
75; FUNC-LABEL: {{^}}sext_in_reg_i1_to_i64:
76; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]]
77; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x10000
78; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]]
79; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]]
80; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}}
81define void @sext_in_reg_i1_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 {
82  %c = shl i64 %a, %b
83  %shl = shl i64 %c, 63
84  %ashr = ashr i64 %shl, 63
85  store i64 %ashr, i64 addrspace(1)* %out, align 8
86  ret void
87}
88
89; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i64:
90; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]]
91; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x80000
92; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]]
93; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]]
94; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}}
95define void @sext_in_reg_i8_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 {
96  %c = shl i64 %a, %b
97  %shl = shl i64 %c, 56
98  %ashr = ashr i64 %shl, 56
99  store i64 %ashr, i64 addrspace(1)* %out, align 8
100  ret void
101}
102
103; FUNC-LABEL: {{^}}sext_in_reg_i16_to_i64:
104; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]]
105; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x100000
106; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]]
107; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]]
108; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}}
109
110define void @sext_in_reg_i16_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 {
111  %c = shl i64 %a, %b
112  %shl = shl i64 %c, 48
113  %ashr = ashr i64 %shl, 48
114  store i64 %ashr, i64 addrspace(1)* %out, align 8
115  ret void
116}
117
118; FUNC-LABEL: {{^}}sext_in_reg_i32_to_i64:
119; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]]
120; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x200000
121; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]]
122; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]]
123; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}}
124define void @sext_in_reg_i32_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 {
125  %c = shl i64 %a, %b
126  %shl = shl i64 %c, 32
127  %ashr = ashr i64 %shl, 32
128  store i64 %ashr, i64 addrspace(1)* %out, align 8
129  ret void
130}
131
132; This is broken on Evergreen for some reason related to the <1 x i64> kernel arguments.
133; XFUNC-LABEL: {{^}}sext_in_reg_i8_to_v1i64:
134; XGCN: s_bfe_i32 [[EXTRACT:s[0-9]+]], {{s[0-9]+}}, 524288
135; XGCN: s_ashr_i32 {{v[0-9]+}}, [[EXTRACT]], 31
136; XGCN: buffer_store_dword
137; XEG: BFE_INT
138; XEG: ASHR
139; define void @sext_in_reg_i8_to_v1i64(<1 x i64> addrspace(1)* %out, <1 x i64> %a, <1 x i64> %b) #0 {
140;   %c = add <1 x i64> %a, %b
141;   %shl = shl <1 x i64> %c, <i64 56>
142;   %ashr = ashr <1 x i64> %shl, <i64 56>
143;   store <1 x i64> %ashr, <1 x i64> addrspace(1)* %out, align 8
144;   ret void
145; }
146
147; FUNC-LABEL: {{^}}v_sext_in_reg_i1_to_i64:
148; SI: buffer_load_dwordx2
149; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
150
151; VI: flat_load_dwordx2
152; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
153
154; GCN: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 1
155; GCN: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]]
156
157; SI: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}}
158; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[HI]]{{\]}}
159define void @v_sext_in_reg_i1_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 {
160  %tid = call i32 @llvm.r600.read.tidig.x()
161  %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
162  %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
163  %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid
164  %a = load i64, i64 addrspace(1)* %a.gep, align 8
165  %b = load i64, i64 addrspace(1)* %b.gep, align 8
166
167  %c = shl i64 %a, %b
168  %shl = shl i64 %c, 63
169  %ashr = ashr i64 %shl, 63
170  store i64 %ashr, i64 addrspace(1)* %out.gep, align 8
171  ret void
172}
173
174; FUNC-LABEL: {{^}}v_sext_in_reg_i8_to_i64:
175; SI: buffer_load_dwordx2
176; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
177
178; VI: flat_load_dwordx2
179; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
180
181; GCN: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 8
182; GCN: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]]
183
184; SI: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}}
185; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[HI]]{{\]}}
186define void @v_sext_in_reg_i8_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 {
187  %tid = call i32 @llvm.r600.read.tidig.x()
188  %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
189  %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
190  %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid
191  %a = load i64, i64 addrspace(1)* %a.gep, align 8
192  %b = load i64, i64 addrspace(1)* %b.gep, align 8
193
194  %c = shl i64 %a, %b
195  %shl = shl i64 %c, 56
196  %ashr = ashr i64 %shl, 56
197  store i64 %ashr, i64 addrspace(1)* %out.gep, align 8
198  ret void
199}
200
201; FUNC-LABEL: {{^}}v_sext_in_reg_i16_to_i64:
202; SI: buffer_load_dwordx2
203; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
204
205; VI: flat_load_dwordx2
206; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
207
208; GCN: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 16
209; GCN: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]]
210
211; SI: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}}
212; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[HI]]{{\]}}
213define void @v_sext_in_reg_i16_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 {
214  %tid = call i32 @llvm.r600.read.tidig.x()
215  %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
216  %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
217  %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid
218  %a = load i64, i64 addrspace(1)* %a.gep, align 8
219  %b = load i64, i64 addrspace(1)* %b.gep, align 8
220
221  %c = shl i64 %a, %b
222  %shl = shl i64 %c, 48
223  %ashr = ashr i64 %shl, 48
224  store i64 %ashr, i64 addrspace(1)* %out.gep, align 8
225  ret void
226}
227
228; FUNC-LABEL: {{^}}v_sext_in_reg_i32_to_i64:
229; SI: buffer_load_dwordx2
230; SI: v_lshl_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}},
231
232; VI: flat_load_dwordx2
233; VI: v_lshlrev_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}},
234
235; GCN: v_ashrrev_i32_e32 v[[SHR:[0-9]+]], 31, v[[LO]]
236; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[SHR]]{{\]}}
237define void @v_sext_in_reg_i32_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 {
238  %tid = call i32 @llvm.r600.read.tidig.x()
239  %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
240  %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
241  %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid
242  %a = load i64, i64 addrspace(1)* %a.gep, align 8
243  %b = load i64, i64 addrspace(1)* %b.gep, align 8
244
245  %c = shl i64 %a, %b
246  %shl = shl i64 %c, 32
247  %ashr = ashr i64 %shl, 32
248  store i64 %ashr, i64 addrspace(1)* %out.gep, align 8
249  ret void
250}
251
252; FUNC-LABEL: {{^}}sext_in_reg_i1_in_i32_other_amount:
253; GCN-NOT: s_lshl
254; GCN-NOT: s_ashr
255; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x190001
256
257; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]]
258; EG-NOT: BFE
259; EG: ADD_INT
260; EG: LSHL
261; EG: ASHR [[RES]]
262; EG: LSHR {{\*?}} [[ADDR]]
263define void @sext_in_reg_i1_in_i32_other_amount(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 {
264  %c = add i32 %a, %b
265  %x = shl i32 %c, 6
266  %y = ashr i32 %x, 7
267  store i32 %y, i32 addrspace(1)* %out
268  ret void
269}
270
271; FUNC-LABEL: {{^}}sext_in_reg_v2i1_in_v2i32_other_amount:
272; GCN-NOT: s_lshl
273; GCN-NOT: s_ashr
274; GCN-DAG: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x190001
275; GCN-DAG: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x190001
276; GCN: s_endpgm
277
278; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]]
279; EG-NOT: BFE
280; EG: ADD_INT
281; EG: LSHL
282; EG: ASHR [[RES]]
283; EG: LSHL
284; EG: ASHR [[RES]]
285; EG: LSHR {{\*?}} [[ADDR]]
286define void @sext_in_reg_v2i1_in_v2i32_other_amount(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 {
287  %c = add <2 x i32> %a, %b
288  %x = shl <2 x i32> %c, <i32 6, i32 6>
289  %y = ashr <2 x i32> %x, <i32 7, i32 7>
290  store <2 x i32> %y, <2 x i32> addrspace(1)* %out
291  ret void
292}
293
294
295; FUNC-LABEL: {{^}}sext_in_reg_v2i1_to_v2i32:
296; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000
297; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000
298; GCN: buffer_store_dwordx2
299
300; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]]
301; EG: BFE_INT [[RES]]
302; EG: BFE_INT [[RES]]
303; EG: LSHR {{\*?}} [[ADDR]]
304define void @sext_in_reg_v2i1_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 {
305  %c = add <2 x i32> %a, %b ; add to prevent folding into extload
306  %shl = shl <2 x i32> %c, <i32 31, i32 31>
307  %ashr = ashr <2 x i32> %shl, <i32 31, i32 31>
308  store <2 x i32> %ashr, <2 x i32> addrspace(1)* %out, align 8
309  ret void
310}
311
312; FUNC-LABEL: {{^}}sext_in_reg_v4i1_to_v4i32:
313; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000
314; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000
315; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000
316; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000
317; GCN: buffer_store_dwordx4
318
319; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW][XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]]
320; EG: BFE_INT [[RES]]
321; EG: BFE_INT [[RES]]
322; EG: BFE_INT [[RES]]
323; EG: BFE_INT [[RES]]
324; EG: LSHR {{\*?}} [[ADDR]]
325define void @sext_in_reg_v4i1_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> %a, <4 x i32> %b) #0 {
326  %c = add <4 x i32> %a, %b ; add to prevent folding into extload
327  %shl = shl <4 x i32> %c, <i32 31, i32 31, i32 31, i32 31>
328  %ashr = ashr <4 x i32> %shl, <i32 31, i32 31, i32 31, i32 31>
329  store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8
330  ret void
331}
332
333; FUNC-LABEL: {{^}}sext_in_reg_v2i8_to_v2i32:
334; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}}
335; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}}
336; GCN: buffer_store_dwordx2
337
338; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]]
339; EG: BFE_INT [[RES]]
340; EG: BFE_INT [[RES]]
341; EG: LSHR {{\*?}} [[ADDR]]
342define void @sext_in_reg_v2i8_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 {
343  %c = add <2 x i32> %a, %b ; add to prevent folding into extload
344  %shl = shl <2 x i32> %c, <i32 24, i32 24>
345  %ashr = ashr <2 x i32> %shl, <i32 24, i32 24>
346  store <2 x i32> %ashr, <2 x i32> addrspace(1)* %out, align 8
347  ret void
348}
349
350; FUNC-LABEL: {{^}}sext_in_reg_v4i8_to_v4i32:
351; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}}
352; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}}
353; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}}
354; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}}
355; GCN: buffer_store_dwordx4
356
357; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW][XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]]
358; EG: BFE_INT [[RES]]
359; EG: BFE_INT [[RES]]
360; EG: BFE_INT [[RES]]
361; EG: BFE_INT [[RES]]
362; EG: LSHR {{\*?}} [[ADDR]]
363define void @sext_in_reg_v4i8_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> %a, <4 x i32> %b) #0 {
364  %c = add <4 x i32> %a, %b ; add to prevent folding into extload
365  %shl = shl <4 x i32> %c, <i32 24, i32 24, i32 24, i32 24>
366  %ashr = ashr <4 x i32> %shl, <i32 24, i32 24, i32 24, i32 24>
367  store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8
368  ret void
369}
370
371; FUNC-LABEL: {{^}}sext_in_reg_v2i16_to_v2i32:
372; GCN: s_sext_i32_i16 {{s[0-9]+}}, {{s[0-9]+}}
373; GCN: s_sext_i32_i16 {{s[0-9]+}}, {{s[0-9]+}}
374; GCN: buffer_store_dwordx2
375
376; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]]
377; EG: BFE_INT [[RES]]
378; EG: BFE_INT [[RES]]
379; EG: LSHR {{\*?}} [[ADDR]]
380define void @sext_in_reg_v2i16_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 {
381  %c = add <2 x i32> %a, %b ; add to prevent folding into extload
382  %shl = shl <2 x i32> %c, <i32 16, i32 16>
383  %ashr = ashr <2 x i32> %shl, <i32 16, i32 16>
384  store <2 x i32> %ashr, <2 x i32> addrspace(1)* %out, align 8
385  ret void
386}
387
388; FUNC-LABEL: {{^}}testcase:
389define void @testcase(i8 addrspace(1)* %out, i8 %a) #0 {
390  %and_a_1 = and i8 %a, 1
391  %cmp_eq = icmp eq i8 %and_a_1, 0
392  %cmp_slt = icmp slt i8 %a, 0
393  %sel0 = select i1 %cmp_slt, i8 0, i8 %a
394  %sel1 = select i1 %cmp_eq, i8 0, i8 %a
395  %xor = xor i8 %sel0, %sel1
396  store i8 %xor, i8 addrspace(1)* %out
397  ret void
398}
399
400; FUNC-LABEL: {{^}}testcase_3:
401define void @testcase_3(i8 addrspace(1)* %out, i8 %a) #0 {
402  %and_a_1 = and i8 %a, 1
403  %cmp_eq = icmp eq i8 %and_a_1, 0
404  %cmp_slt = icmp slt i8 %a, 0
405  %sel0 = select i1 %cmp_slt, i8 0, i8 %a
406  %sel1 = select i1 %cmp_eq, i8 0, i8 %a
407  %xor = xor i8 %sel0, %sel1
408  store i8 %xor, i8 addrspace(1)* %out
409  ret void
410}
411
412; FUNC-LABEL: {{^}}vgpr_sext_in_reg_v4i8_to_v4i32:
413; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8
414; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8
415; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8
416; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8
417define void @vgpr_sext_in_reg_v4i8_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %a, <4 x i32> addrspace(1)* %b) #0 {
418  %loada = load <4 x i32>, <4 x i32> addrspace(1)* %a, align 16
419  %loadb = load <4 x i32>, <4 x i32> addrspace(1)* %b, align 16
420  %c = add <4 x i32> %loada, %loadb ; add to prevent folding into extload
421  %shl = shl <4 x i32> %c, <i32 24, i32 24, i32 24, i32 24>
422  %ashr = ashr <4 x i32> %shl, <i32 24, i32 24, i32 24, i32 24>
423  store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8
424  ret void
425}
426
427; FUNC-LABEL: {{^}}vgpr_sext_in_reg_v4i16_to_v4i32:
428; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 16
429; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 16
430define void @vgpr_sext_in_reg_v4i16_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %a, <4 x i32> addrspace(1)* %b) #0 {
431  %loada = load <4 x i32>, <4 x i32> addrspace(1)* %a, align 16
432  %loadb = load <4 x i32>, <4 x i32> addrspace(1)* %b, align 16
433  %c = add <4 x i32> %loada, %loadb ; add to prevent folding into extload
434  %shl = shl <4 x i32> %c, <i32 16, i32 16, i32 16, i32 16>
435  %ashr = ashr <4 x i32> %shl, <i32 16, i32 16, i32 16, i32 16>
436  store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8
437  ret void
438}
439
440; FUNC-LABEL: {{^}}sext_in_reg_to_illegal_type:
441; GCN: buffer_load_sbyte
442; GCN: v_max_i32
443; GCN-NOT: bfe
444; GCN: buffer_store_short
445define void @sext_in_reg_to_illegal_type(i16 addrspace(1)* nocapture %out, i8 addrspace(1)* nocapture %src) #0 {
446  %tmp5 = load i8, i8 addrspace(1)* %src, align 1
447  %tmp2 = sext i8 %tmp5 to i32
448  %tmp2.5 = icmp sgt i32 %tmp2, 0
449  %tmp3 = select i1 %tmp2.5, i32 %tmp2, i32 0
450  %tmp4 = trunc i32 %tmp3 to i8
451  %tmp6 = sext i8 %tmp4 to i16
452  store i16 %tmp6, i16 addrspace(1)* %out, align 2
453  ret void
454}
455
456declare i32 @llvm.AMDGPU.bfe.i32(i32, i32, i32) nounwind readnone
457
458; FUNC-LABEL: {{^}}bfe_0_width:
459; GCN-NOT: {{[^@]}}bfe
460; GCN: s_endpgm
461define void @bfe_0_width(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 {
462  %load = load i32, i32 addrspace(1)* %ptr, align 4
463  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 8, i32 0) nounwind readnone
464  store i32 %bfe, i32 addrspace(1)* %out, align 4
465  ret void
466}
467
468; FUNC-LABEL: {{^}}bfe_8_bfe_8:
469; GCN: v_bfe_i32
470; GCN-NOT: {{[^@]}}bfe
471; GCN: s_endpgm
472define void @bfe_8_bfe_8(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 {
473  %load = load i32, i32 addrspace(1)* %ptr, align 4
474  %bfe0 = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 0, i32 8) nounwind readnone
475  %bfe1 = call i32 @llvm.AMDGPU.bfe.i32(i32 %bfe0, i32 0, i32 8) nounwind readnone
476  store i32 %bfe1, i32 addrspace(1)* %out, align 4
477  ret void
478}
479
480; FUNC-LABEL: {{^}}bfe_8_bfe_16:
481; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 8
482; GCN: s_endpgm
483define void @bfe_8_bfe_16(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 {
484  %load = load i32, i32 addrspace(1)* %ptr, align 4
485  %bfe0 = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 0, i32 8) nounwind readnone
486  %bfe1 = call i32 @llvm.AMDGPU.bfe.i32(i32 %bfe0, i32 0, i32 16) nounwind readnone
487  store i32 %bfe1, i32 addrspace(1)* %out, align 4
488  ret void
489}
490
491; This really should be folded into 1
492; FUNC-LABEL: {{^}}bfe_16_bfe_8:
493; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 8
494; GCN-NOT: {{[^@]}}bfe
495; GCN: s_endpgm
496define void @bfe_16_bfe_8(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 {
497  %load = load i32, i32 addrspace(1)* %ptr, align 4
498  %bfe0 = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 0, i32 16) nounwind readnone
499  %bfe1 = call i32 @llvm.AMDGPU.bfe.i32(i32 %bfe0, i32 0, i32 8) nounwind readnone
500  store i32 %bfe1, i32 addrspace(1)* %out, align 4
501  ret void
502}
503
504; Make sure there isn't a redundant BFE
505; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i32_bfe:
506; GCN: s_sext_i32_i8 s{{[0-9]+}}, s{{[0-9]+}}
507; GCN-NOT: {{[^@]}}bfe
508; GCN: s_endpgm
509define void @sext_in_reg_i8_to_i32_bfe(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 {
510  %c = add i32 %a, %b ; add to prevent folding into extload
511  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %c, i32 0, i32 8) nounwind readnone
512  %shl = shl i32 %bfe, 24
513  %ashr = ashr i32 %shl, 24
514  store i32 %ashr, i32 addrspace(1)* %out, align 4
515  ret void
516}
517
518; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i32_bfe_wrong:
519define void @sext_in_reg_i8_to_i32_bfe_wrong(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 {
520  %c = add i32 %a, %b ; add to prevent folding into extload
521  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %c, i32 8, i32 0) nounwind readnone
522  %shl = shl i32 %bfe, 24
523  %ashr = ashr i32 %shl, 24
524  store i32 %ashr, i32 addrspace(1)* %out, align 4
525  ret void
526}
527
528; FUNC-LABEL: {{^}}sextload_i8_to_i32_bfe:
529; GCN: buffer_load_sbyte
530; GCN-NOT: {{[^@]}}bfe
531; GCN: s_endpgm
532define void @sextload_i8_to_i32_bfe(i32 addrspace(1)* %out, i8 addrspace(1)* %ptr) #0 {
533  %load = load i8, i8 addrspace(1)* %ptr, align 1
534  %sext = sext i8 %load to i32
535  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %sext, i32 0, i32 8) nounwind readnone
536  %shl = shl i32 %bfe, 24
537  %ashr = ashr i32 %shl, 24
538  store i32 %ashr, i32 addrspace(1)* %out, align 4
539  ret void
540}
541
542; GCN: .text
543; FUNC-LABEL: {{^}}sextload_i8_to_i32_bfe_0:{{.*$}}
544; GCN-NOT: {{[^@]}}bfe
545; GCN: s_endpgm
546define void @sextload_i8_to_i32_bfe_0(i32 addrspace(1)* %out, i8 addrspace(1)* %ptr) #0 {
547  %load = load i8, i8 addrspace(1)* %ptr, align 1
548  %sext = sext i8 %load to i32
549  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %sext, i32 8, i32 0) nounwind readnone
550  %shl = shl i32 %bfe, 24
551  %ashr = ashr i32 %shl, 24
552  store i32 %ashr, i32 addrspace(1)* %out, align 4
553  ret void
554}
555
556; FUNC-LABEL: {{^}}sext_in_reg_i1_bfe_offset_0:
557; GCN-NOT: shr
558; GCN-NOT: shl
559; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 1
560; GCN: s_endpgm
561define void @sext_in_reg_i1_bfe_offset_0(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
562  %x = load i32, i32 addrspace(1)* %in, align 4
563  %shl = shl i32 %x, 31
564  %shr = ashr i32 %shl, 31
565  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %shr, i32 0, i32 1)
566  store i32 %bfe, i32 addrspace(1)* %out, align 4
567  ret void
568}
569
570; FUNC-LABEL: {{^}}sext_in_reg_i1_bfe_offset_1:
571; GCN: buffer_load_dword
572; GCN-NOT: shl
573; GCN-NOT: shr
574; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 1, 1
575; GCN: s_endpgm
576define void @sext_in_reg_i1_bfe_offset_1(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
577  %x = load i32, i32 addrspace(1)* %in, align 4
578  %shl = shl i32 %x, 30
579  %shr = ashr i32 %shl, 30
580  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %shr, i32 1, i32 1)
581  store i32 %bfe, i32 addrspace(1)* %out, align 4
582  ret void
583}
584
585; FUNC-LABEL: {{^}}sext_in_reg_i2_bfe_offset_1:
586; GCN: buffer_load_dword
587; GCN-NOT: v_lshl
588; GCN-NOT: v_ashr
589; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 2
590; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 1, 2
591; GCN: s_endpgm
592define void @sext_in_reg_i2_bfe_offset_1(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 {
593  %x = load i32, i32 addrspace(1)* %in, align 4
594  %shl = shl i32 %x, 30
595  %shr = ashr i32 %shl, 30
596  %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %shr, i32 1, i32 2)
597  store i32 %bfe, i32 addrspace(1)* %out, align 4
598  ret void
599}
600
601; Make sure we propagate the VALUness to users of a moved scalar BFE.
602
603; FUNC-LABEL: {{^}}v_sext_in_reg_i1_to_i64_move_use:
604; SI: buffer_load_dwordx2
605; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
606
607; VI: flat_load_dwordx2
608; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}}
609
610; GCN-DAG: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 1
611; GCN-DAG: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]]
612; GCN-DAG: v_and_b32_e32 v[[RESULT_LO:[0-9]+]], s{{[0-9]+}}, v[[LO]]
613; GCN-DAG: v_and_b32_e32 v[[RESULT_HI:[0-9]+]], s{{[0-9]+}}, v[[HI]]
614; SI: buffer_store_dwordx2 v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}}
615; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}}
616define void @v_sext_in_reg_i1_to_i64_move_use(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr, i64 %s.val) #0 {
617  %tid = call i32 @llvm.r600.read.tidig.x()
618  %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
619  %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
620  %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid
621  %a = load i64, i64 addrspace(1)* %a.gep, align 8
622  %b = load i64, i64 addrspace(1)* %b.gep, align 8
623
624  %c = shl i64 %a, %b
625  %shl = shl i64 %c, 63
626  %ashr = ashr i64 %shl, 63
627
628  %and = and i64 %ashr, %s.val
629  store i64 %and, i64 addrspace(1)* %out.gep, align 8
630  ret void
631}
632
633; FUNC-LABEL: {{^}}v_sext_in_reg_i32_to_i64_move_use:
634; SI: buffer_load_dwordx2
635; SI: v_lshl_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}},
636
637; VI: flat_load_dwordx2
638; VI: v_lshlrev_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}},
639
640; GCN-DAG: v_ashrrev_i32_e32 v[[SHR:[0-9]+]], 31, v[[LO]]
641; GCN-DAG: v_and_b32_e32 v[[RESULT_LO:[0-9]+]], s{{[0-9]+}}, v[[LO]]
642; GCN-DAG: v_and_b32_e32 v[[RESULT_HI:[0-9]+]], s{{[0-9]+}}, v[[SHR]]
643
644; SI: buffer_store_dwordx2 v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}}
645; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}}
646define void @v_sext_in_reg_i32_to_i64_move_use(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr, i64 %s.val) #0 {
647  %tid = call i32 @llvm.r600.read.tidig.x()
648  %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
649  %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid
650  %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid
651  %a = load i64, i64 addrspace(1)* %a.gep, align 8
652  %b = load i64, i64 addrspace(1)* %b.gep, align 8
653
654  %c = shl i64 %a, %b
655  %shl = shl i64 %c, 32
656  %ashr = ashr i64 %shl, 32
657  %and = and i64 %ashr, %s.val
658  store i64 %and, i64 addrspace(1)* %out.gep, align 8
659  ret void
660}
661
662declare i32 @llvm.r600.read.tidig.x() #1
663
664attributes #0 = { nounwind }
665attributes #1 = { nounwind readnone }
666