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