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: ; mask branch [[EXIT:BB[0-9]+_[0-9]+]]
224; CHECK-NEXT: s_cbranch_execz [[EXIT]]
225
226; CHECK: {{BB[0-9]+_[0-9]+}}: ; %bb.preheader
227; CHECK: s_mov_b32
228
229; CHECK: [[LOOP_BB:BB[0-9]+_[0-9]+]]:
230
231; CHECK: v_mov_b32_e64 v7, -1
232; CHECK: v_nop_e64
233; CHECK: v_cmpx_gt_f32_e32 vcc, 0, v7
234
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]]
240
241; CHECK-NEXT: {{^}}[[EXIT]]:
242; CHECK: s_or_b64 exec, exec, [[SAVEEXEC]]
243; CHECK: buffer_store_dword
244; CHECK: s_endpgm
245define amdgpu_ps void @test_kill_divergent_loop(i32 %arg) #0 {
246entry:
247  %cmp = icmp eq i32 %arg, 0
248  br i1 %cmp, label %bb, label %exit
249
250bb:
251  %var = call float asm sideeffect "
252    v_mov_b32_e64 v7, -1
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
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
268
269exit:
270  store volatile i32 8, i32 addrspace(1)* undef
271  ret void
272}
273
274; bug 28550
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]+]]
279
280; CHECK: exp
281; CHECK-NEXT: s_endpgm
282
283; CHECK: [[KILLBB:BB[0-9]+_[0-9]+]]:
284; CHECK-NEXT: s_cbranch_scc0 [[PHIBB:BB[0-9]+_[0-9]+]]
285
286; CHECK: [[PHIBB]]:
287; CHECK: v_cmp_eq_f32_e32 vcc, 0, [[PHIREG]]
288; CHECK: s_cbranch_vccz [[ENDBB:BB[0-9]+_[0-9]+]]
289
290; CHECK: ; %bb10
291; CHECK: v_mov_b32_e32 v{{[0-9]+}}, 9
292; CHECK: buffer_store_dword
293
294; CHECK: [[ENDBB]]:
295; CHECK-NEXT: s_endpgm
296define amdgpu_ps void @phi_use_def_before_kill(float inreg %x) #0 {
297bb:
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
304
305phibb:
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
309
310bb8:
311  store volatile i32 8, i32 addrspace(1)* undef
312  br label %phibb
313
314bb10:
315  store volatile i32 9, i32 addrspace(1)* undef
316  br label %end
317
318end:
319  ret void
320}
321
322; CHECK-LABEL: {{^}}no_skip_no_successors:
323; CHECK: v_cmp_nge_f32
324; CHECK: s_cbranch_vccz [[SKIPKILL:BB[0-9]+_[0-9]+]]
325
326; CHECK: ; %bb6
327; CHECK: s_mov_b64 exec, 0
328
329; CHECK: [[SKIPKILL]]:
330; CHECK: v_cmp_nge_f32_e32 vcc
331; CHECK: %bb.3: ; %bb5
332; CHECK-NEXT: .Lfunc_end{{[0-9]+}}
333define amdgpu_ps void @no_skip_no_successors(float inreg %arg, float inreg %arg1) #0 {
334bb:
335  %tmp = fcmp ult float %arg1, 0.000000e+00
336  %tmp2 = fcmp ult float %arg, 0x3FCF5C2900000000
337  br i1 %tmp, label %bb6, label %bb3
338
339bb3:                                              ; preds = %bb
340  br i1 %tmp2, label %bb5, label %bb4
341
342bb4:                                              ; preds = %bb3
343  br i1 true, label %bb5, label %bb7
344
345bb5:                                              ; preds = %bb4, %bb3
346  unreachable
347
348bb6:                                              ; preds = %bb
349  call void @llvm.amdgcn.kill(i1 false)
350  unreachable
351
352bb7:                                              ; preds = %bb4
353  ret void
354}
355
356; CHECK-LABEL: {{^}}if_after_kill_block:
357; CHECK: ; %bb.0:
358; CHECK: s_and_saveexec_b64
359; CHECK: s_xor_b64
360; CHECK-NEXT: mask branch [[BB4:BB[0-9]+_[0-9]+]]
361
362; CHECK: v_cmpx_gt_f32_e32 vcc, 0,
363; CHECK: [[BB4]]:
364; CHECK: s_or_b64 exec, exec
365; CHECK: image_sample_c
366
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-NOT: branch
371
372; CHECK: BB{{[0-9]+_[0-9]+}}: ; %bb8
373; CHECK: buffer_store_dword
374
375; CHECK: [[END]]:
376; CHECK: s_endpgm
377define amdgpu_ps void @if_after_kill_block(float %arg, float %arg1, float %arg2, float %arg3) #0 {
378bb:
379  %tmp = fcmp ult float %arg1, 0.000000e+00
380  br i1 %tmp, label %bb3, label %bb4
381
382bb3:                                              ; preds = %bb
383  %cmp.arg = fcmp olt float %arg, 0.0
384  call void @llvm.amdgcn.kill(i1 %cmp.arg)
385  br label %bb4
386
387bb4:                                              ; preds = %bb3, %bb
388  %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)
389  %tmp6 = extractelement <4 x float> %tmp5, i32 0
390  %tmp7 = fcmp une float %tmp6, 0.000000e+00
391  br i1 %tmp7, label %bb8, label %bb9
392
393bb8:                                              ; preds = %bb9, %bb4
394  store volatile i32 9, i32 addrspace(1)* undef
395  ret void
396
397bb9:                                              ; preds = %bb4
398  ret void
399}
400
401declare <4 x float> @llvm.amdgcn.image.sample.c.1d.v4f32.f32(i32, float, float, <8 x i32>, <4 x i32>, i1, i32, i32) #1
402declare void @llvm.amdgcn.kill(i1) #0
403
404attributes #0 = { nounwind }
405attributes #1 = { nounwind readonly }
406