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