1; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck %s
2
3; CHECK-LABEL: {{^}}test_kill_depth_0_imm_pos:
4; CHECK-NEXT: ; %bb.0:
5; CHECK-NEXT: ; %bb.1:
6; CHECK-NEXT: s_endpgm
7define amdgpu_ps void @test_kill_depth_0_imm_pos() #0 {
8  call void @llvm.amdgcn.kill(i1 true)
9  ret void
10}
11
12; CHECK-LABEL: {{^}}test_kill_depth_0_imm_neg:
13; CHECK-NEXT: ; %bb.0:
14; CHECK-NEXT: s_mov_b64 exec, 0
15; CHECK-NEXT: ; %bb.1:
16; CHECK-NEXT: s_endpgm
17define amdgpu_ps void @test_kill_depth_0_imm_neg() #0 {
18  call void @llvm.amdgcn.kill(i1 false)
19  ret void
20}
21
22; FIXME: Ideally only one would be emitted
23; CHECK-LABEL: {{^}}test_kill_depth_0_imm_neg_x2:
24; CHECK-NEXT: ; %bb.0:
25; CHECK-NEXT: s_mov_b64 exec, 0
26; CHECK-NEXT: ; %bb.1:
27; CHECK-NEXT: s_mov_b64 exec, 0
28; CHECK-NEXT: ; %bb.2:
29; CHECK-NEXT: s_endpgm
30define amdgpu_ps void @test_kill_depth_0_imm_neg_x2() #0 {
31  call void @llvm.amdgcn.kill(i1 false)
32  call void @llvm.amdgcn.kill(i1 false)
33  ret void
34}
35
36; CHECK-LABEL: {{^}}test_kill_depth_var:
37; CHECK-NEXT: ; %bb.0:
38; CHECK-NEXT: v_cmpx_gt_f32_e32 vcc, 0, v0
39; CHECK-NEXT: ; %bb.1:
40; CHECK-NEXT: s_endpgm
41define amdgpu_ps void @test_kill_depth_var(float %x) #0 {
42  %cmp = fcmp olt float %x, 0.0
43  call void @llvm.amdgcn.kill(i1 %cmp)
44  ret void
45}
46
47; FIXME: Ideally only one would be emitted
48; CHECK-LABEL: {{^}}test_kill_depth_var_x2_same:
49; CHECK-NEXT: ; %bb.0:
50; CHECK-NEXT: v_cmpx_gt_f32_e32 vcc, 0, v0
51; CHECK-NEXT: ; %bb.1:
52; CHECK-NEXT: v_cmpx_gt_f32_e32 vcc, 0, v0
53; CHECK-NEXT: ; %bb.2:
54; CHECK-NEXT: s_endpgm
55define amdgpu_ps void @test_kill_depth_var_x2_same(float %x) #0 {
56  %cmp = fcmp olt float %x, 0.0
57  call void @llvm.amdgcn.kill(i1 %cmp)
58  call void @llvm.amdgcn.kill(i1 %cmp)
59  ret void
60}
61
62; CHECK-LABEL: {{^}}test_kill_depth_var_x2:
63; CHECK-NEXT: ; %bb.0:
64; CHECK-NEXT: v_cmpx_gt_f32_e32 vcc, 0, v0
65; CHECK-NEXT: ; %bb.1:
66; CHECK-NEXT: v_cmpx_gt_f32_e32 vcc, 0, v1
67; CHECK-NEXT: ; %bb.2:
68; CHECK-NEXT: s_endpgm
69define amdgpu_ps void @test_kill_depth_var_x2(float %x, float %y) #0 {
70  %cmp.x = fcmp olt float %x, 0.0
71  call void @llvm.amdgcn.kill(i1 %cmp.x)
72  %cmp.y = fcmp olt float %y, 0.0
73  call void @llvm.amdgcn.kill(i1 %cmp.y)
74  ret void
75}
76
77; CHECK-LABEL: {{^}}test_kill_depth_var_x2_instructions:
78; CHECK-NEXT: ; %bb.0:
79; CHECK-NEXT: v_cmpx_gt_f32_e32 vcc, 0, v0
80; CHECK-NEXT: s_cbranch_execnz BB6_2
81; CHECK-NEXT: ; %bb.1:
82; CHECK-NEXT: exp
83; CHECK-NEXT: s_endpgm
84; CHECK-NEXT: BB6_2:
85; CHECK: v_mov_b32_e64 v7, -1
86; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
87; CHECK-NEXT: s_cbranch_execnz BB6_4
88; CHECK-NEXT: ; %bb.3:
89; CHECK-NEXT: exp
90; CHECK-NEXT: s_endpgm
91; CHECK-NEXT: BB6_4:
92; CHECK-NEXT: s_endpgm
93define amdgpu_ps void @test_kill_depth_var_x2_instructions(float %x) #0 {
94  %cmp.x = fcmp olt float %x, 0.0
95  call void @llvm.amdgcn.kill(i1 %cmp.x)
96  %y = call float asm sideeffect "v_mov_b32_e64 v7, -1", "={v7}"()
97  %cmp.y = fcmp olt float %y, 0.0
98  call void @llvm.amdgcn.kill(i1 %cmp.y)
99  ret void
100}
101
102; FIXME: why does the skip depend on the asm length in the same block?
103
104; CHECK-LABEL: {{^}}test_kill_control_flow:
105; CHECK: s_cmp_lg_u32 s{{[0-9]+}}, 0
106; CHECK: s_cbranch_scc1 [[RETURN_BB:BB[0-9]+_[0-9]+]]
107
108; CHECK-NEXT: ; %bb.1:
109; CHECK: v_mov_b32_e64 v7, -1
110; CHECK: v_nop_e64
111; CHECK: v_nop_e64
112; CHECK: v_nop_e64
113; CHECK: v_nop_e64
114; CHECK: v_nop_e64
115; CHECK: v_nop_e64
116; CHECK: v_nop_e64
117; CHECK: v_nop_e64
118; CHECK: v_nop_e64
119; CHECK: v_nop_e64
120
121; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
122; CHECK-NEXT: s_cbranch_execnz [[SPLIT_BB:BB[0-9]+_[0-9]+]]
123; CHECK-NEXT: ; %bb.2:
124; CHECK-NEXT: exp null off, off, off, off done vm
125; CHECK-NEXT: s_endpgm
126
127; CHECK-NEXT: {{^}}[[SPLIT_BB]]:
128; CHECK-NEXT: s_endpgm
129define amdgpu_ps void @test_kill_control_flow(i32 inreg %arg) #0 {
130entry:
131  %cmp = icmp eq i32 %arg, 0
132  br i1 %cmp, label %bb, label %exit
133
134bb:
135  %var = call float asm sideeffect "
136    v_mov_b32_e64 v7, -1
137    v_nop_e64
138    v_nop_e64
139    v_nop_e64
140    v_nop_e64
141    v_nop_e64
142    v_nop_e64
143    v_nop_e64
144    v_nop_e64
145    v_nop_e64
146    v_nop_e64", "={v7}"()
147  %cmp.var = fcmp olt float %var, 0.0
148  call void @llvm.amdgcn.kill(i1 %cmp.var)
149  br label %exit
150
151exit:
152  ret void
153}
154
155; CHECK-LABEL: {{^}}test_kill_control_flow_remainder:
156; CHECK: s_cmp_lg_u32 s{{[0-9]+}}, 0
157; CHECK-NEXT: v_mov_b32_e32 v{{[0-9]+}}, 0
158; CHECK-NEXT: s_cbranch_scc1 [[RETURN_BB:BB[0-9]+_[0-9]+]]
159
160; CHECK-NEXT: ; %bb.1: ; %bb
161; CHECK: v_mov_b32_e64 v7, -1
162; CHECK: v_nop_e64
163; CHECK: v_nop_e64
164; CHECK: v_nop_e64
165; CHECK: v_nop_e64
166; CHECK: v_nop_e64
167; CHECK: v_nop_e64
168; CHECK: v_nop_e64
169; CHECK: v_nop_e64
170; CHECK: ;;#ASMEND
171; CHECK: v_mov_b32_e64 v8, -1
172; CHECK: ;;#ASMEND
173; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
174; CHECK-NEXT: s_cbranch_execnz [[SPLIT_BB:BB[0-9]+_[0-9]+]]
175
176; CHECK-NEXT: ; %bb.2:
177; CHECK-NEXT: exp null off, off, off, off done vm
178; CHECK-NEXT: s_endpgm
179
180; CHECK-NEXT: {{^}}[[SPLIT_BB]]:
181; CHECK: buffer_store_dword v8
182; CHECK: v_mov_b32_e64 v9, -2
183
184; CHECK: {{^}}BB{{[0-9]+_[0-9]+}}:
185; CHECK: buffer_store_dword v9
186; CHECK-NEXT: s_endpgm
187define amdgpu_ps void @test_kill_control_flow_remainder(i32 inreg %arg) #0 {
188entry:
189  %cmp = icmp eq i32 %arg, 0
190  br i1 %cmp, label %bb, label %exit
191
192bb:
193  %var = call float asm sideeffect "
194    v_mov_b32_e64 v7, -1
195    v_nop_e64
196    v_nop_e64
197    v_nop_e64
198    v_nop_e64
199    v_nop_e64
200    v_nop_e64
201    v_nop_e64
202    v_nop_e64
203    v_nop_e64
204    v_nop_e64
205    v_nop_e64", "={v7}"()
206  %live.across = call float asm sideeffect "v_mov_b32_e64 v8, -1", "={v8}"()
207  %cmp.var = fcmp olt float %var, 0.0
208  call void @llvm.amdgcn.kill(i1 %cmp.var)
209  store volatile float %live.across, float addrspace(1)* undef
210  %live.out = call float asm sideeffect "v_mov_b32_e64 v9, -2", "={v9}"()
211  br label %exit
212
213exit:
214  %phi = phi float [ 0.0, %entry ], [ %live.out, %bb ]
215  store float %phi, float addrspace(1)* undef
216  ret void
217}
218
219; CHECK-LABEL: {{^}}test_kill_divergent_loop:
220; CHECK: v_cmp_eq_u32_e32 vcc, 0, v0
221; CHECK-NEXT: s_and_saveexec_b64 [[SAVEEXEC:s\[[0-9]+:[0-9]+\]]], vcc
222; CHECK-NEXT: s_xor_b64 [[SAVEEXEC]], exec, [[SAVEEXEC]]
223; CHECK-NEXT: s_cbranch_execz [[EXIT:BB[0-9]+_[0-9]+]]
224
225; CHECK: ; %bb.{{[0-9]+}}: ; %bb.preheader
226; CHECK: s_mov_b32
227
228; CHECK: [[LOOP_BB:BB[0-9]+_[0-9]+]]:
229
230; CHECK: v_mov_b32_e64 v7, -1
231; CHECK: v_nop_e64
232; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
233
234; CHECK-NEXT: ; %bb.3:
235; CHECK: buffer_load_dword [[LOAD:v[0-9]+]]
236; CHECK: v_cmp_eq_u32_e32 vcc, 0, [[LOAD]]
237; CHECK-NEXT: s_and_b64 vcc, exec, vcc
238; CHECK-NEXT: s_cbranch_vccnz [[LOOP_BB]]
239
240; CHECK-NEXT: {{^}}[[EXIT]]:
241; CHECK: s_or_b64 exec, exec, [[SAVEEXEC]]
242; CHECK: buffer_store_dword
243; CHECK: s_endpgm
244define amdgpu_ps void @test_kill_divergent_loop(i32 %arg) #0 {
245entry:
246  %cmp = icmp eq i32 %arg, 0
247  br i1 %cmp, label %bb, label %exit
248
249bb:
250  %var = call float asm sideeffect "
251    v_mov_b32_e64 v7, -1
252    v_nop_e64
253    v_nop_e64
254    v_nop_e64
255    v_nop_e64
256    v_nop_e64
257    v_nop_e64
258    v_nop_e64
259    v_nop_e64
260    v_nop_e64
261    v_nop_e64", "={v7}"()
262  %cmp.var = fcmp olt float %var, 0.0
263  call void @llvm.amdgcn.kill(i1 %cmp.var)
264  %vgpr = load volatile i32, i32 addrspace(1)* undef
265  %loop.cond = icmp eq i32 %vgpr, 0
266  br i1 %loop.cond, label %bb, label %exit
267
268exit:
269  store volatile i32 8, i32 addrspace(1)* undef
270  ret void
271}
272
273; bug 28550
274; CHECK-LABEL: {{^}}phi_use_def_before_kill:
275; CHECK: v_cndmask_b32_e64 [[PHIREG:v[0-9]+]], 0, -1.0,
276; CHECK: v_cmpx_lt_f32_e32 vcc, 0,
277; CHECK-NEXT: s_cbranch_execnz [[BB4:BB[0-9]+_[0-9]+]]
278
279; CHECK: exp
280; CHECK-NEXT: s_endpgm
281
282; CHECK: [[KILLBB:BB[0-9]+_[0-9]+]]:
283; CHECK-NEXT: s_cbranch_scc0 [[PHIBB:BB[0-9]+_[0-9]+]]
284
285; CHECK: [[PHIBB]]:
286; CHECK: v_cmp_eq_f32_e32 vcc, 0, [[PHIREG]]
287; CHECK: s_cbranch_vccz [[ENDBB:BB[0-9]+_[0-9]+]]
288
289; CHECK: ; %bb10
290; CHECK: v_mov_b32_e32 v{{[0-9]+}}, 9
291; CHECK: buffer_store_dword
292
293; CHECK: [[ENDBB]]:
294; CHECK-NEXT: s_endpgm
295define amdgpu_ps void @phi_use_def_before_kill(float inreg %x) #0 {
296bb:
297  %tmp = fadd float %x, 1.000000e+00
298  %tmp1 = fcmp olt float 0.000000e+00, %tmp
299  %tmp2 = select i1 %tmp1, float -1.000000e+00, float 0.000000e+00
300  %cmp.tmp2 = fcmp olt float %tmp2, 0.0
301  call void @llvm.amdgcn.kill(i1 %cmp.tmp2)
302  br i1 undef, label %phibb, label %bb8
303
304phibb:
305  %tmp5 = phi float [ %tmp2, %bb ], [ 4.0, %bb8 ]
306  %tmp6 = fcmp oeq float %tmp5, 0.000000e+00
307  br i1 %tmp6, label %bb10, label %end
308
309bb8:
310  store volatile i32 8, i32 addrspace(1)* undef
311  br label %phibb
312
313bb10:
314  store volatile i32 9, i32 addrspace(1)* undef
315  br label %end
316
317end:
318  ret void
319}
320
321; CHECK-LABEL: {{^}}no_skip_no_successors:
322; CHECK: v_cmp_nge_f32
323; CHECK: s_cbranch_vccz [[SKIPKILL:BB[0-9]+_[0-9]+]]
324
325; CHECK: ; %bb6
326; CHECK: s_mov_b64 exec, 0
327
328; CHECK: [[SKIPKILL]]:
329; CHECK: v_cmp_nge_f32_e32 vcc
330; CHECK: %bb.3: ; %bb5
331; CHECK-NEXT: .Lfunc_end{{[0-9]+}}
332define amdgpu_ps void @no_skip_no_successors(float inreg %arg, float inreg %arg1) #0 {
333bb:
334  %tmp = fcmp ult float %arg1, 0.000000e+00
335  %tmp2 = fcmp ult float %arg, 0x3FCF5C2900000000
336  br i1 %tmp, label %bb6, label %bb3
337
338bb3:                                              ; preds = %bb
339  br i1 %tmp2, label %bb5, label %bb4
340
341bb4:                                              ; preds = %bb3
342  br i1 true, label %bb5, label %bb7
343
344bb5:                                              ; preds = %bb4, %bb3
345  unreachable
346
347bb6:                                              ; preds = %bb
348  call void @llvm.amdgcn.kill(i1 false)
349  unreachable
350
351bb7:                                              ; preds = %bb4
352  ret void
353}
354
355; CHECK-LABEL: {{^}}if_after_kill_block:
356; CHECK: ; %bb.0:
357; CHECK: s_and_saveexec_b64
358; CHECK: s_xor_b64
359
360; CHECK: v_cmpx_gt_f32_e32 vcc, 0,
361; CHECK: BB{{[0-9]+_[0-9]+}}:
362; CHECK: s_or_b64 exec, exec
363; CHECK: image_sample_c
364
365; CHECK: v_cmp_neq_f32_e32 vcc, 0,
366; CHECK: s_and_saveexec_b64 s{{\[[0-9]+:[0-9]+\]}}, vcc
367; CHECK-NEXT: s_cbranch_execz [[END:BB[0-9]+_[0-9]+]]
368; CHECK-NOT: branch
369
370; CHECK: ; %bb.{{[0-9]+}}: ; %bb8
371; CHECK: buffer_store_dword
372
373; CHECK: [[END]]:
374; CHECK: s_endpgm
375define amdgpu_ps void @if_after_kill_block(float %arg, float %arg1, float %arg2, float %arg3) #0 {
376bb:
377  %tmp = fcmp ult float %arg1, 0.000000e+00
378  br i1 %tmp, label %bb3, label %bb4
379
380bb3:                                              ; preds = %bb
381  %cmp.arg = fcmp olt float %arg, 0.0
382  call void @llvm.amdgcn.kill(i1 %cmp.arg)
383  br label %bb4
384
385bb4:                                              ; preds = %bb3, %bb
386  %tmp5 = call <4 x float> @llvm.amdgcn.image.sample.c.1d.v4f32.f32(i32 16, float %arg2, float %arg3, <8 x i32> undef, <4 x i32> undef, i1 0, i32 0, i32 0)
387  %tmp6 = extractelement <4 x float> %tmp5, i32 0
388  %tmp7 = fcmp une float %tmp6, 0.000000e+00
389  br i1 %tmp7, label %bb8, label %bb9
390
391bb8:                                              ; preds = %bb9, %bb4
392  store volatile i32 9, i32 addrspace(1)* undef
393  ret void
394
395bb9:                                              ; preds = %bb4
396  ret void
397}
398
399; CHECK-LABEL: {{^}}cbranch_kill:
400; CHECK-NOT: exp null off, off, off, off done vm
401define amdgpu_ps void @cbranch_kill(i32 inreg %0, <2 x float> %1) {
402.entry:
403  %val0 = extractelement <2 x float> %1, i32 0
404  %val1 = extractelement <2 x float> %1, i32 1
405  %p0 = call float @llvm.amdgcn.interp.p1(float %val0, i32 immarg 0, i32 immarg 1, i32 %0) #2
406  %sample = call float @llvm.amdgcn.image.sample.l.2darray.f32.f32(i32 1, float %p0, float %p0, float %p0, float 0.000000e+00, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0)
407  %cond0 = fcmp ugt float %sample, 0.000000e+00
408  br i1 %cond0, label %live, label %kill
409
410kill:
411  call void @llvm.amdgcn.kill(i1 false)
412  br label %export
413
414live:
415  %i0 = call float @llvm.amdgcn.interp.p1(float %val0, i32 immarg 0, i32 immarg 0, i32 %0) #2
416  %i1 = call float @llvm.amdgcn.interp.p2(float %i0, float %val1, i32 immarg 0, i32 immarg 0, i32 %0) #2
417  %i2 = call float @llvm.amdgcn.interp.p1(float %val0, i32 immarg 1, i32 immarg 0, i32 %0) #2
418  %i3 = call float @llvm.amdgcn.interp.p2(float %i2, float %val1, i32 immarg 1, i32 immarg 0, i32 %0) #2
419  %scale.i0 = fmul reassoc nnan nsz arcp contract float %i0, %sample
420  %scale.i1 = fmul reassoc nnan nsz arcp contract float %i1, %sample
421  %scale.i2 = fmul reassoc nnan nsz arcp contract float %i2, %sample
422  %scale.i3 = fmul reassoc nnan nsz arcp contract float %i3, %sample
423  br label %export
424
425export:
426  %proxy.0.0 = phi float [ undef, %kill ], [ %scale.i0, %live ]
427  %proxy.0.1 = phi float [ undef, %kill ], [ %scale.i1, %live ]
428  %proxy.0.2 = phi float [ undef, %kill ], [ %scale.i2, %live ]
429  %proxy.0.3 = phi float [ undef, %kill ], [ %scale.i3, %live ]
430  %out.0 = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %proxy.0.0, float %proxy.0.1) #2
431  %out.1 = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %proxy.0.2, float %proxy.0.3) #2
432  call void @llvm.amdgcn.exp.compr.v2f16(i32 immarg 0, i32 immarg 15, <2 x half> %out.0, <2 x half> %out.1, i1 immarg true, i1 immarg true) #3
433  ret void
434}
435
436declare float @llvm.amdgcn.interp.p1(float, i32 immarg, i32 immarg, i32) #2
437declare float @llvm.amdgcn.interp.p2(float, float, i32 immarg, i32 immarg, i32) #2
438declare void @llvm.amdgcn.exp.compr.v2f16(i32 immarg, i32 immarg, <2 x half>, <2 x half>, i1 immarg, i1 immarg) #3
439declare <2 x half> @llvm.amdgcn.cvt.pkrtz(float, float) #2
440declare float @llvm.amdgcn.image.sample.l.2darray.f32.f32(i32 immarg, float, float, float, float, <8 x i32>, <4 x i32>, i1 immarg, i32 immarg, i32 immarg) #1
441declare <4 x float> @llvm.amdgcn.image.sample.c.1d.v4f32.f32(i32, float, float, <8 x i32>, <4 x i32>, i1, i32, i32) #1
442declare void @llvm.amdgcn.kill(i1) #0
443
444attributes #0 = { nounwind }
445attributes #1 = { nounwind readonly }
446attributes #2 = { nounwind readnone speculatable }
447attributes #3 = { inaccessiblememonly nounwind writeonly }
448