1 ; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck %s
3 ; CHECK-LABEL: {{^}}test_kill_depth_0_imm_pos:
7 define amdgpu_ps void @test_kill_depth_0_imm_pos() #0 {
8 call void @llvm.amdgcn.kill(i1 true)
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
17 define amdgpu_ps void @test_kill_depth_0_imm_neg() #0 {
18 call void @llvm.amdgcn.kill(i1 false)
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
30 define 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)
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
41 define 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)
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
55 define 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)
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
69 define 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)
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:
83 ; CHECK-NEXT: s_endpgm
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:
90 ; CHECK-NEXT: s_endpgm
92 ; CHECK-NEXT: s_endpgm
93 define 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)
102 ; FIXME: why does the skip depend on the asm length in the same block?
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]+]]
108 ; CHECK-NEXT: ; %bb.1:
109 ; CHECK: v_mov_b32_e64 v7, -1
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
127 ; CHECK-NEXT: {{^}}[[SPLIT_BB]]:
128 ; CHECK-NEXT: s_endpgm
129 define amdgpu_ps void @test_kill_control_flow(i32 inreg %arg) #0 {
131 %cmp = icmp eq i32 %arg, 0
132 br i1 %cmp, label %bb, label %exit
135 %var = call float asm sideeffect "
146 v_nop_e64", "={v7}"()
147 %cmp.var = fcmp olt float %var, 0.0
148 call void @llvm.amdgcn.kill(i1 %cmp.var)
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]+]]
160 ; CHECK-NEXT: ; %bb.1: ; %bb
161 ; CHECK: v_mov_b32_e64 v7, -1
171 ; CHECK: v_mov_b32_e64 v8, -1
173 ; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
174 ; CHECK-NEXT: s_cbranch_execnz [[SPLIT_BB:BB[0-9]+_[0-9]+]]
176 ; CHECK-NEXT: ; %bb.2:
177 ; CHECK-NEXT: exp null off, off, off, off done vm
178 ; CHECK-NEXT: s_endpgm
180 ; CHECK-NEXT: {{^}}[[SPLIT_BB]]:
181 ; CHECK: buffer_store_dword v8
182 ; CHECK: v_mov_b32_e64 v9, -2
184 ; CHECK: {{^}}BB{{[0-9]+_[0-9]+}}:
185 ; CHECK: buffer_store_dword v9
186 ; CHECK-NEXT: s_endpgm
187 define amdgpu_ps void @test_kill_control_flow_remainder(i32 inreg %arg) #0 {
189 %cmp = icmp eq i32 %arg, 0
190 br i1 %cmp, label %bb, label %exit
193 %var = call float asm sideeffect "
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}"()
214 %phi = phi float [ 0.0, %entry ], [ %live.out, %bb ]
215 store float %phi, float addrspace(1)* undef
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: ; mask branch [[EXIT:BB[0-9]+_[0-9]+]]
224 ; CHECK-NEXT: s_cbranch_execz [[EXIT]]
226 ; CHECK: {{BB[0-9]+_[0-9]+}}: ; %bb.preheader
229 ; CHECK: [[LOOP_BB:BB[0-9]+_[0-9]+]]:
231 ; CHECK: v_mov_b32_e64 v7, -1
233 ; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
235 ; CHECK-NEXT: ; %bb.3:
236 ; CHECK: buffer_load_dword [[LOAD:v[0-9]+]]
237 ; CHECK: v_cmp_eq_u32_e32 vcc, 0, [[LOAD]]
238 ; CHECK-NEXT: s_and_b64 vcc, exec, vcc
239 ; CHECK-NEXT: s_cbranch_vccnz [[LOOP_BB]]
241 ; CHECK-NEXT: {{^}}[[EXIT]]:
242 ; CHECK: s_or_b64 exec, exec, [[SAVEEXEC]]
243 ; CHECK: buffer_store_dword
245 define amdgpu_ps void @test_kill_divergent_loop(i32 %arg) #0 {
247 %cmp = icmp eq i32 %arg, 0
248 br i1 %cmp, label %bb, label %exit
251 %var = call float asm sideeffect "
262 v_nop_e64", "={v7}"()
263 %cmp.var = fcmp olt float %var, 0.0
264 call void @llvm.amdgcn.kill(i1 %cmp.var)
265 %vgpr = load volatile i32, i32 addrspace(1)* undef
266 %loop.cond = icmp eq i32 %vgpr, 0
267 br i1 %loop.cond, label %bb, label %exit
270 store volatile i32 8, i32 addrspace(1)* undef
275 ; CHECK-LABEL: {{^}}phi_use_def_before_kill:
276 ; CHECK: v_cndmask_b32_e64 [[PHIREG:v[0-9]+]], 0, -1.0,
277 ; CHECK: v_cmpx_lt_f32_e32 vcc, 0,
278 ; CHECK-NEXT: s_cbranch_execnz [[BB4:BB[0-9]+_[0-9]+]]
281 ; CHECK-NEXT: s_endpgm
283 ; CHECK: [[KILLBB:BB[0-9]+_[0-9]+]]:
284 ; CHECK-NEXT: s_cbranch_scc0 [[PHIBB:BB[0-9]+_[0-9]+]]
287 ; CHECK: v_cmp_eq_f32_e32 vcc, 0, [[PHIREG]]
288 ; CHECK: s_cbranch_vccz [[ENDBB:BB[0-9]+_[0-9]+]]
291 ; CHECK: v_mov_b32_e32 v{{[0-9]+}}, 9
292 ; CHECK: buffer_store_dword
295 ; CHECK-NEXT: s_endpgm
296 define amdgpu_ps void @phi_use_def_before_kill(float inreg %x) #0 {
298 %tmp = fadd float %x, 1.000000e+00
299 %tmp1 = fcmp olt float 0.000000e+00, %tmp
300 %tmp2 = select i1 %tmp1, float -1.000000e+00, float 0.000000e+00
301 %cmp.tmp2 = fcmp olt float %tmp2, 0.0
302 call void @llvm.amdgcn.kill(i1 %cmp.tmp2)
303 br i1 undef, label %phibb, label %bb8
306 %tmp5 = phi float [ %tmp2, %bb ], [ 4.0, %bb8 ]
307 %tmp6 = fcmp oeq float %tmp5, 0.000000e+00
308 br i1 %tmp6, label %bb10, label %end
311 store volatile i32 8, i32 addrspace(1)* undef
315 store volatile i32 9, i32 addrspace(1)* undef
322 ; CHECK-LABEL: {{^}}no_skip_no_successors:
323 ; CHECK: v_cmp_nge_f32
324 ; CHECK: s_cbranch_vccz [[SKIPKILL:BB[0-9]+_[0-9]+]]
327 ; CHECK: s_mov_b64 exec, 0
329 ; CHECK: [[SKIPKILL]]:
330 ; CHECK: v_cmp_nge_f32_e32 vcc
331 ; CHECK: %bb.3: ; %bb5
332 ; CHECK-NEXT: .Lfunc_end{{[0-9]+}}
333 define amdgpu_ps void @no_skip_no_successors(float inreg %arg, float inreg %arg1) #0 {
335 %tmp = fcmp ult float %arg1, 0.000000e+00
336 %tmp2 = fcmp ult float %arg, 0x3FCF5C2900000000
337 br i1 %tmp, label %bb6, label %bb3
340 br i1 %tmp2, label %bb5, label %bb4
343 br i1 true, label %bb5, label %bb7
345 bb5: ; preds = %bb4, %bb3
349 call void @llvm.amdgcn.kill(i1 false)
356 ; CHECK-LABEL: {{^}}if_after_kill_block:
358 ; CHECK: s_and_saveexec_b64
360 ; CHECK-NEXT: mask branch [[BB4:BB[0-9]+_[0-9]+]]
362 ; CHECK: v_cmpx_gt_f32_e32 vcc, 0,
364 ; CHECK: s_or_b64 exec, exec
365 ; CHECK: image_sample_c
367 ; CHECK: v_cmp_neq_f32_e32 vcc, 0,
368 ; CHECK: s_and_saveexec_b64 s{{\[[0-9]+:[0-9]+\]}}, vcc
369 ; CHECK: mask branch [[END:BB[0-9]+_[0-9]+]]
370 ; CHECK-NEXT: s_cbranch_execz [[END]]
373 ; CHECK: BB{{[0-9]+_[0-9]+}}: ; %bb8
374 ; CHECK: buffer_store_dword
378 define amdgpu_ps void @if_after_kill_block(float %arg, float %arg1, float %arg2, float %arg3) #0 {
380 %tmp = fcmp ult float %arg1, 0.000000e+00
381 br i1 %tmp, label %bb3, label %bb4
384 %cmp.arg = fcmp olt float %arg, 0.0
385 call void @llvm.amdgcn.kill(i1 %cmp.arg)
388 bb4: ; preds = %bb3, %bb
389 %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)
390 %tmp6 = extractelement <4 x float> %tmp5, i32 0
391 %tmp7 = fcmp une float %tmp6, 0.000000e+00
392 br i1 %tmp7, label %bb8, label %bb9
394 bb8: ; preds = %bb9, %bb4
395 store volatile i32 9, i32 addrspace(1)* undef
402 declare <4 x float> @llvm.amdgcn.image.sample.c.1d.v4f32.f32(i32, float, float, <8 x i32>, <4 x i32>, i1, i32, i32) #1
403 declare void @llvm.amdgcn.kill(i1) #0
405 attributes #0 = { nounwind }
406 attributes #1 = { nounwind readonly }