297 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=amdgcn -mcpu=tonga < %s | FileCheck -enable-var-scope -check-prefix=CHECK %s3 4; Check that WQM is not triggered by the softwqm intrinsic alone.5;6define amdgpu_ps float @test1(i32 inreg %idx0, i32 inreg %idx1) {7; CHECK-LABEL: test1:8; CHECK: ; %bb.0: ; %main_body9; CHECK-NEXT: v_mov_b32_e32 v0, s010; CHECK-NEXT: v_mov_b32_e32 v1, s111; CHECK-NEXT: buffer_load_dword v0, v0, s[0:3], 0 idxen12; CHECK-NEXT: buffer_load_dword v1, v1, s[0:3], 0 idxen13; CHECK-NEXT: s_waitcnt vmcnt(0)14; CHECK-NEXT: v_add_f32_e32 v0, v0, v115; CHECK-NEXT: ; kill: def $vgpr0 killed $vgpr0 killed $exec16; CHECK-NEXT: ; return to shader part epilog17main_body:18 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)19 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)20 %out = fadd float %src0, %src121 %out.0 = call float @llvm.amdgcn.softwqm.f32(float %out)22 ret float %out.023}24 25; Check that the softwqm intrinsic works correctly for integers.26;27define amdgpu_ps float @test2(i32 inreg %idx0, i32 inreg %idx1) {28; CHECK-LABEL: test2:29; CHECK: ; %bb.0: ; %main_body30; CHECK-NEXT: v_mov_b32_e32 v0, s031; CHECK-NEXT: v_mov_b32_e32 v1, s132; CHECK-NEXT: buffer_load_dword v0, v0, s[0:3], 0 idxen33; CHECK-NEXT: buffer_load_dword v1, v1, s[0:3], 0 idxen34; CHECK-NEXT: s_waitcnt vmcnt(0)35; CHECK-NEXT: v_add_f32_e32 v0, v0, v136; CHECK-NEXT: ; kill: def $vgpr0 killed $vgpr0 killed $exec37; CHECK-NEXT: ; return to shader part epilog38main_body:39 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)40 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)41 %out = fadd float %src0, %src142 %out.0 = bitcast float %out to i3243 %out.1 = call i32 @llvm.amdgcn.softwqm.i32(i32 %out.0)44 %out.2 = bitcast i32 %out.1 to float45 ret float %out.246}47 48; Make sure the transition from WQM to Exact to softwqm does not trigger WQM.49;50define amdgpu_ps float @test_softwqm1(i32 inreg %idx0, i32 inreg %idx1) {51; CHECK-LABEL: test_softwqm1:52; CHECK: ; %bb.0: ; %main_body53; CHECK-NEXT: v_mov_b32_e32 v0, s054; CHECK-NEXT: v_mov_b32_e32 v2, s155; CHECK-NEXT: buffer_load_dword v1, v0, s[0:3], 0 idxen56; CHECK-NEXT: buffer_load_dword v2, v2, s[0:3], 0 idxen57; CHECK-NEXT: s_waitcnt vmcnt(0)58; CHECK-NEXT: v_add_f32_e32 v1, v1, v259; CHECK-NEXT: buffer_store_dword v1, v0, s[0:3], 0 idxen60; CHECK-NEXT: v_add_f32_e32 v0, v1, v161; CHECK-NEXT: ; kill: def $vgpr0 killed $vgpr0 killed $exec62; CHECK-NEXT: s_waitcnt vmcnt(0)63; CHECK-NEXT: ; return to shader part epilog64main_body:65 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)66 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)67 %temp = fadd float %src0, %src168 call void @llvm.amdgcn.struct.buffer.store.f32(float %temp, <4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)69 %out = fadd float %temp, %temp70 %out.0 = call float @llvm.amdgcn.softwqm.f32(float %out)71 ret float %out.072}73 74; Make sure the transition from WQM to Exact to softwqm does trigger WQM.75;76define amdgpu_ps float @test_softwqm2(i32 inreg %idx0, i32 inreg %idx1) {77; CHECK-LABEL: test_softwqm2:78; CHECK: ; %bb.0: ; %main_body79; CHECK-NEXT: s_mov_b64 s[2:3], exec80; CHECK-NEXT: s_wqm_b64 exec, exec81; CHECK-NEXT: v_mov_b32_e32 v0, s082; CHECK-NEXT: v_mov_b32_e32 v2, s183; CHECK-NEXT: buffer_load_dword v1, v0, s[0:3], 0 idxen84; CHECK-NEXT: buffer_load_dword v2, v2, s[0:3], 0 idxen85; CHECK-NEXT: s_waitcnt vmcnt(0)86; CHECK-NEXT: v_add_f32_e32 v1, v1, v287; CHECK-NEXT: v_mov_b32_e32 v2, v188; CHECK-NEXT: v_add_f32_e32 v1, v1, v189; CHECK-NEXT: s_and_b64 exec, exec, s[2:3]90; CHECK-NEXT: buffer_store_dword v2, v0, s[0:3], 0 idxen91; CHECK-NEXT: s_wqm_b64 exec, exec92; CHECK-NEXT: v_mov_b32_e32 v0, v193; CHECK-NEXT: s_and_b64 exec, exec, s[2:3]94; CHECK-NEXT: s_waitcnt vmcnt(0)95; CHECK-NEXT: ; return to shader part epilog96main_body:97 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)98 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)99 %temp = fadd float %src0, %src1100 %temp.0 = call float @llvm.amdgcn.wqm.f32(float %temp)101 call void @llvm.amdgcn.struct.buffer.store.f32(float %temp.0, <4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)102 %out = fadd float %temp, %temp103 %out.0 = call float @llvm.amdgcn.softwqm.f32(float %out)104 ret float %out.0105}106 107; NOTE: llvm.amdgcn.wwm is deprecated, use llvm.amdgcn.strict.wwm instead.108; Make sure the transition from Exact to STRICT_WWM then softwqm does not trigger WQM.109;110define amdgpu_ps float @test_wwm1(i32 inreg %idx0, i32 inreg %idx1) {111; CHECK-LABEL: test_wwm1:112; CHECK: ; %bb.0: ; %main_body113; CHECK-NEXT: s_or_saveexec_b64 s[2:3], -1114; CHECK-NEXT: v_mov_b32_e32 v1, s0115; CHECK-NEXT: buffer_load_dword v2, v1, s[0:3], 0 idxen116; CHECK-NEXT: s_mov_b64 exec, s[2:3]117; CHECK-NEXT: s_waitcnt vmcnt(0)118; CHECK-NEXT: buffer_store_dword v2, v1, s[0:3], 0 idxen119; CHECK-NEXT: s_or_saveexec_b64 s[2:3], -1120; CHECK-NEXT: v_mov_b32_e32 v1, s1121; CHECK-NEXT: buffer_load_dword v1, v1, s[0:3], 0 idxen122; CHECK-NEXT: s_waitcnt vmcnt(0)123; CHECK-NEXT: v_add_f32_e32 v1, v2, v1124; CHECK-NEXT: s_mov_b64 exec, s[2:3]125; CHECK-NEXT: v_mov_b32_e32 v0, v1126; CHECK-NEXT: v_add_f32_e32 v0, v0, v0127; CHECK-NEXT: ; kill: def $vgpr0 killed $vgpr0 killed $exec128; CHECK-NEXT: ; return to shader part epilog129main_body:130 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)131 call void @llvm.amdgcn.struct.buffer.store.f32(float %src0, <4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)132 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)133 %temp = fadd float %src0, %src1134 %temp.0 = call float @llvm.amdgcn.wwm.f32(float %temp)135 %out = fadd float %temp.0, %temp.0136 %out.0 = call float @llvm.amdgcn.softwqm.f32(float %out)137 ret float %out.0138}139 140; Make sure the transition from Exact to STRICT_WWM then softwqm does not trigger WQM.141;142define amdgpu_ps float @test_strict_wwm1(i32 inreg %idx0, i32 inreg %idx1) {143; CHECK-LABEL: test_strict_wwm1:144; CHECK: ; %bb.0: ; %main_body145; CHECK-NEXT: s_or_saveexec_b64 s[2:3], -1146; CHECK-NEXT: v_mov_b32_e32 v1, s0147; CHECK-NEXT: buffer_load_dword v2, v1, s[0:3], 0 idxen148; CHECK-NEXT: s_mov_b64 exec, s[2:3]149; CHECK-NEXT: s_waitcnt vmcnt(0)150; CHECK-NEXT: buffer_store_dword v2, v1, s[0:3], 0 idxen151; CHECK-NEXT: s_or_saveexec_b64 s[2:3], -1152; CHECK-NEXT: v_mov_b32_e32 v1, s1153; CHECK-NEXT: buffer_load_dword v1, v1, s[0:3], 0 idxen154; CHECK-NEXT: s_waitcnt vmcnt(0)155; CHECK-NEXT: v_add_f32_e32 v1, v2, v1156; CHECK-NEXT: s_mov_b64 exec, s[2:3]157; CHECK-NEXT: v_mov_b32_e32 v0, v1158; CHECK-NEXT: v_add_f32_e32 v0, v0, v0159; CHECK-NEXT: ; kill: def $vgpr0 killed $vgpr0 killed $exec160; CHECK-NEXT: ; return to shader part epilog161main_body:162 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)163 call void @llvm.amdgcn.struct.buffer.store.f32(float %src0, <4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)164 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)165 %temp = fadd float %src0, %src1166 %temp.0 = call float @llvm.amdgcn.strict.wwm.f32(float %temp)167 %out = fadd float %temp.0, %temp.0168 %out.0 = call float @llvm.amdgcn.softwqm.f32(float %out)169 ret float %out.0170}171 172 173; Check that softwqm on one case of branch does not trigger WQM for shader.174;175define amdgpu_ps float @test_control_flow_0(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 inreg %idx0, i32 inreg %idx1, i32 %c, i32 %z, float %data) {176; CHECK-LABEL: test_control_flow_0:177; CHECK: ; %bb.0: ; %main_body178; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1179; CHECK-NEXT: s_and_saveexec_b64 s[0:1], vcc180; CHECK-NEXT: s_xor_b64 s[0:1], exec, s[0:1]181; CHECK-NEXT: s_cbranch_execz .LBB6_2182; CHECK-NEXT: ; %bb.1: ; %ELSE183; CHECK-NEXT: buffer_store_dword v2, v0, s[0:3], 0 idxen184; CHECK-NEXT: .LBB6_2: ; %Flow185; CHECK-NEXT: s_andn2_saveexec_b64 s[0:1], s[0:1]186; CHECK-NEXT: s_cbranch_execz .LBB6_4187; CHECK-NEXT: ; %bb.3: ; %IF188; CHECK-NEXT: v_mov_b32_e32 v0, s12189; CHECK-NEXT: v_mov_b32_e32 v1, s13190; CHECK-NEXT: buffer_load_dword v0, v0, s[0:3], 0 idxen191; CHECK-NEXT: buffer_load_dword v1, v1, s[0:3], 0 idxen192; CHECK-NEXT: s_waitcnt vmcnt(0)193; CHECK-NEXT: v_add_f32_e32 v2, v0, v1194; CHECK-NEXT: ; kill: def $vgpr2 killed $vgpr2 killed $exec195; CHECK-NEXT: .LBB6_4: ; %END196; CHECK-NEXT: s_or_b64 exec, exec, s[0:1]197; CHECK-NEXT: v_mov_b32_e32 v0, v2198; CHECK-NEXT: s_waitcnt vmcnt(0)199; CHECK-NEXT: ; return to shader part epilog200main_body:201 %cmp = icmp eq i32 %z, 0202 br i1 %cmp, label %IF, label %ELSE203 204IF:205 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)206 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)207 %out = fadd float %src0, %src1208 %data.if = call float @llvm.amdgcn.softwqm.f32(float %out)209 br label %END210 211ELSE:212 call void @llvm.amdgcn.struct.buffer.store.f32(float %data, <4 x i32> poison, i32 %c, i32 0, i32 0, i32 0)213 br label %END214 215END:216 %r = phi float [ %data.if, %IF ], [ %data, %ELSE ]217 ret float %r218}219 220; Check that softwqm on one case of branch is treated as WQM in WQM shader.221;222define amdgpu_ps float @test_control_flow_1(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 inreg %idx0, i32 inreg %idx1, i32 %c, i32 %z, float %data) {223; CHECK-LABEL: test_control_flow_1:224; CHECK: ; %bb.0: ; %main_body225; CHECK-NEXT: s_mov_b64 s[14:15], exec226; CHECK-NEXT: s_wqm_b64 exec, exec227; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1228; CHECK-NEXT: s_and_saveexec_b64 s[16:17], vcc229; CHECK-NEXT: s_xor_b64 s[16:17], exec, s[16:17]230; CHECK-NEXT: s_cbranch_execz .LBB7_2231; CHECK-NEXT: ; %bb.1: ; %ELSE232; CHECK-NEXT: image_sample v1, v0, s[0:7], s[8:11] dmask:0x1233; CHECK-NEXT: s_and_saveexec_b64 s[18:19], s[14:15]234; CHECK-NEXT: s_waitcnt vmcnt(0)235; CHECK-NEXT: image_sample v1, v1, s[0:7], s[8:11] dmask:0x1236; CHECK-NEXT: s_waitcnt vmcnt(0)237; CHECK-NEXT: buffer_store_dword v1, v0, s[0:3], 0 idxen238; CHECK-NEXT: s_mov_b64 exec, s[18:19]239; CHECK-NEXT: .LBB7_2: ; %Flow240; CHECK-NEXT: s_andn2_saveexec_b64 s[0:1], s[16:17]241; CHECK-NEXT: s_cbranch_execz .LBB7_4242; CHECK-NEXT: ; %bb.3: ; %IF243; CHECK-NEXT: v_mov_b32_e32 v0, s12244; CHECK-NEXT: v_mov_b32_e32 v1, s13245; CHECK-NEXT: buffer_load_dword v0, v0, s[0:3], 0 idxen246; CHECK-NEXT: buffer_load_dword v1, v1, s[0:3], 0 idxen247; CHECK-NEXT: s_waitcnt vmcnt(0)248; CHECK-NEXT: v_add_f32_e32 v2, v0, v1249; CHECK-NEXT: ; kill: def $vgpr2 killed $vgpr2 killed $exec250; CHECK-NEXT: .LBB7_4: ; %END251; CHECK-NEXT: s_or_b64 exec, exec, s[0:1]252; CHECK-NEXT: s_and_b64 exec, exec, s[14:15]253; CHECK-NEXT: v_mov_b32_e32 v0, v2254; CHECK-NEXT: s_waitcnt vmcnt(0)255; CHECK-NEXT: ; return to shader part epilog256main_body:257 %cmp = icmp eq i32 %z, 0258 br i1 %cmp, label %IF, label %ELSE259 260IF:261 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx0, i32 0, i32 0, i32 0)262 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> poison, i32 %idx1, i32 0, i32 0, i32 0)263 %out = fadd float %src0, %src1264 %data.if = call float @llvm.amdgcn.softwqm.f32(float %out)265 br label %END266 267ELSE:268 %c.bc = bitcast i32 %c to float269 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %c.bc, <8 x i32> %rsrc, <4 x i32> %sampler, i1 0, i32 0, i32 0) #0270 %tex0 = extractelement <4 x float> %tex, i32 0271 %dtex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %tex0, <8 x i32> %rsrc, <4 x i32> %sampler, i1 0, i32 0, i32 0) #0272 %data.sample = extractelement <4 x float> %dtex, i32 0273 274 call void @llvm.amdgcn.struct.buffer.store.f32(float %data.sample, <4 x i32> poison, i32 %c, i32 0, i32 0, i32 0)275 br label %END276 277END:278 %r = phi float [ %data.if, %IF ], [ %data, %ELSE ]279 ret float %r280}281 282declare void @llvm.amdgcn.struct.buffer.store.f32(float, <4 x i32>, i32, i32, i32, i32 immarg) #2283declare void @llvm.amdgcn.struct.buffer.store.v4f32(<4 x float>, <4 x i32>, i32, i32, i32, i32 immarg) #2284declare float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32>, i32, i32, i32, i32 immarg) #3285declare <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32, float, <8 x i32>, <4 x i32>, i1, i32, i32) #3286declare <4 x float> @llvm.amdgcn.image.sample.2d.v4f32.f32(i32, float, float, <8 x i32>, <4 x i32>, i1, i32, i32) #3287declare float @llvm.amdgcn.wqm.f32(float) #3288declare float @llvm.amdgcn.softwqm.f32(float) #3289declare i32 @llvm.amdgcn.softwqm.i32(i32) #3290declare float @llvm.amdgcn.strict.wwm.f32(float) #3291declare float @llvm.amdgcn.wwm.f32(float) #3292declare void @llvm.amdgcn.wqm.demote(i1) #1293 294attributes #1 = { nounwind }295attributes #2 = { nounwind readonly }296attributes #3 = { nounwind readnone }297