1; RUN: llc -march=amdgcn -mcpu=verde -verify-machineinstrs < %s | FileCheck -check-prefix=CHECK -check-prefix=SI %s 2; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=CHECK -check-prefix=VI %s 3 4; Check that WQM isn't triggered by image load/store intrinsics. 5; 6;CHECK-LABEL: {{^}}test1: 7;CHECK-NOT: s_wqm 8define amdgpu_ps <4 x float> @test1(<8 x i32> inreg %rsrc, i32 %c) { 9main_body: 10 %tex = call <4 x float> @llvm.amdgcn.image.load.1d.v4f32.i32(i32 15, i32 %c, <8 x i32> %rsrc, i32 0, i32 0) 11 call void @llvm.amdgcn.image.store.1d.v4f32.i32(<4 x float> %tex, i32 15, i32 %c, <8 x i32> %rsrc, i32 0, i32 0) 12 ret <4 x float> %tex 13} 14 15; Check that WQM is triggered by code calculating inputs to image samples and is disabled as soon as possible 16; 17;CHECK-LABEL: {{^}}test2: 18;CHECK-NEXT: ; %main_body 19;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 20;CHECK-NEXT: s_wqm_b64 exec, exec 21;CHECK: interp 22;CHECK: s_and_b64 exec, exec, [[ORIG]] 23;CHECK-NOT: interp 24;CHECK: image_sample 25;CHECK-NOT: exec 26;CHECK: .size test2 27define amdgpu_ps <4 x float> @test2(i32 inreg, i32 inreg, i32 inreg, i32 inreg %m0, <8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, <2 x float> %pos) #6 { 28main_body: 29 %inst23 = extractelement <2 x float> %pos, i32 0 30 %inst24 = extractelement <2 x float> %pos, i32 1 31 %inst25 = tail call float @llvm.amdgcn.interp.p1(float %inst23, i32 0, i32 0, i32 %m0) 32 %inst26 = tail call float @llvm.amdgcn.interp.p2(float %inst25, float %inst24, i32 0, i32 0, i32 %m0) 33 %inst28 = tail call float @llvm.amdgcn.interp.p1(float %inst23, i32 1, i32 0, i32 %m0) 34 %inst29 = tail call float @llvm.amdgcn.interp.p2(float %inst28, float %inst24, i32 1, i32 0, i32 %m0) 35 %tex = call <4 x float> @llvm.amdgcn.image.sample.2d.v4f32.f32(i32 15, float %inst26, float %inst29, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 36 ret <4 x float> %tex 37} 38 39; ... but disabled for stores (and, in this simple case, not re-enabled) ... 40; 41;CHECK-LABEL: {{^}}test3: 42;CHECK-NEXT: ; %main_body 43;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 44;CHECK-NEXT: s_wqm_b64 exec, exec 45;CHECK: s_and_b64 exec, exec, [[ORIG]] 46;CHECK: image_sample 47;CHECK: store 48;CHECK-NOT: exec 49;CHECK: .size test3 50define amdgpu_ps <4 x float> @test3(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, float %c) { 51main_body: 52 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %c, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 53 %tex.1 = bitcast <4 x float> %tex to <4 x i32> 54 %tex.2 = extractelement <4 x i32> %tex.1, i32 0 55 56 call void @llvm.amdgcn.struct.buffer.store.v4f32(<4 x float> %tex, <4 x i32> undef, i32 %tex.2, i32 0, i32 0, i32 0) 57 58 ret <4 x float> %tex 59} 60 61; ... and disabled for export. 62; 63;CHECK-LABEL: {{^}}test3x: 64;CHECK-NEXT: ; %main_body 65;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 66;CHECK-NEXT: s_wqm_b64 exec, exec 67;CHECK: s_and_b64 exec, exec, [[ORIG]] 68;CHECK: image_sample 69;CHECK: exp 70;CHECK-NOT: exec 71;CHECK: .size test3x 72define amdgpu_ps void @test3x(i32 inreg, i32 inreg, i32 inreg, i32 inreg %m0, <8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, <2 x float> %pos) #6 { 73main_body: 74 %inst23 = extractelement <2 x float> %pos, i32 0 75 %inst24 = extractelement <2 x float> %pos, i32 1 76 %inst25 = tail call float @llvm.amdgcn.interp.p1(float %inst23, i32 0, i32 0, i32 %m0) 77 %inst26 = tail call float @llvm.amdgcn.interp.p2(float %inst25, float %inst24, i32 0, i32 0, i32 %m0) 78 %inst28 = tail call float @llvm.amdgcn.interp.p1(float %inst23, i32 1, i32 0, i32 %m0) 79 %inst29 = tail call float @llvm.amdgcn.interp.p2(float %inst28, float %inst24, i32 1, i32 0, i32 %m0) 80 %tex = call <4 x float> @llvm.amdgcn.image.sample.2d.v4f32.f32(i32 15, float %inst26, float %inst29, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 81 %tex.0 = extractelement <4 x float> %tex, i32 0 82 %tex.1 = extractelement <4 x float> %tex, i32 1 83 %tex.2 = extractelement <4 x float> %tex, i32 2 84 %tex.3 = extractelement <4 x float> %tex, i32 3 85 call void @llvm.amdgcn.exp.f32(i32 0, i32 15, float %tex.0, float %tex.1, float %tex.2, float %tex.3, i1 true, i1 true) 86 ret void 87} 88 89; Check that WQM is re-enabled when required. 90; 91;CHECK-LABEL: {{^}}test4: 92;CHECK-NEXT: ; %main_body 93;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 94;CHECK-NEXT: s_wqm_b64 exec, exec 95;CHECK: v_mul_lo_u32 [[MUL:v[0-9]+]], v0, v1 96;CHECK: s_and_b64 exec, exec, [[ORIG]] 97;CHECK: store 98;CHECK: s_wqm_b64 exec, exec 99;CHECK: image_sample 100;CHECK: image_sample 101define amdgpu_ps <4 x float> @test4(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, float addrspace(1)* inreg %ptr, i32 %c, i32 %d, float %data) { 102main_body: 103 %c.1 = mul i32 %c, %d 104 105 call void @llvm.amdgcn.struct.buffer.store.v4f32(<4 x float> undef, <4 x i32> undef, i32 %c.1, i32 0, i32 0, i32 0) 106 %c.1.bc = bitcast i32 %c.1 to float 107 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %c.1.bc, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 108 %tex0 = extractelement <4 x float> %tex, i32 0 109 %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 false, i32 0, i32 0) #0 110 ret <4 x float> %dtex 111} 112 113; Check that WQM is triggered by the wqm intrinsic. 114; 115;CHECK-LABEL: {{^}}test5: 116;CHECK: s_wqm_b64 exec, exec 117;CHECK: buffer_load_dword 118;CHECK: buffer_load_dword 119;CHECK: v_add_f32_e32 120; WQM was inserting an unecessary v_mov to self after the v_add. Make sure this 121; does not happen - the v_add should write the return reg directly. 122;CHECK-NOT: v_mov_b32_e32 123define amdgpu_ps float @test5(i32 inreg %idx0, i32 inreg %idx1) { 124main_body: 125 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 126 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 127 %out = fadd float %src0, %src1 128 %out.0 = call float @llvm.amdgcn.wqm.f32(float %out) 129 ret float %out.0 130} 131 132; Check that the wqm intrinsic works correctly for integers. 133; 134;CHECK-LABEL: {{^}}test6: 135;CHECK: s_wqm_b64 exec, exec 136;CHECK: buffer_load_dword 137;CHECK: buffer_load_dword 138;CHECK: v_add_f32_e32 139define amdgpu_ps float @test6(i32 inreg %idx0, i32 inreg %idx1) { 140main_body: 141 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 142 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 143 %out = fadd float %src0, %src1 144 %out.0 = bitcast float %out to i32 145 %out.1 = call i32 @llvm.amdgcn.wqm.i32(i32 %out.0) 146 %out.2 = bitcast i32 %out.1 to float 147 ret float %out.2 148} 149 150; Check that WWM is triggered by the wwm intrinsic. 151; 152;CHECK-LABEL: {{^}}test_wwm1: 153;CHECK: s_or_saveexec_b64 s{{\[[0-9]+:[0-9]+\]}}, -1 154;CHECK: buffer_load_dword 155;CHECK: buffer_load_dword 156;CHECK: v_add_f32_e32 157define amdgpu_ps float @test_wwm1(i32 inreg %idx0, i32 inreg %idx1) { 158main_body: 159 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 160 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 161 %out = fadd float %src0, %src1 162 %out.0 = call float @llvm.amdgcn.wwm.f32(float %out) 163 ret float %out.0 164} 165 166; Same as above, but with an integer type. 167; 168;CHECK-LABEL: {{^}}test_wwm2: 169;CHECK: s_or_saveexec_b64 s{{\[[0-9]+:[0-9]+\]}}, -1 170;CHECK: buffer_load_dword 171;CHECK: buffer_load_dword 172;CHECK: v_add_{{[iu]}}32_e32 173define amdgpu_ps float @test_wwm2(i32 inreg %idx0, i32 inreg %idx1) { 174main_body: 175 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 176 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 177 %src0.0 = bitcast float %src0 to i32 178 %src1.0 = bitcast float %src1 to i32 179 %out = add i32 %src0.0, %src1.0 180 %out.0 = call i32 @llvm.amdgcn.wwm.i32(i32 %out) 181 %out.1 = bitcast i32 %out.0 to float 182 ret float %out.1 183} 184 185; Check that we don't leave WWM on for computations that don't require WWM, 186; since that will lead clobbering things that aren't supposed to be clobbered 187; in cases like this. 188; 189;CHECK-LABEL: {{^}}test_wwm3: 190;CHECK: s_or_saveexec_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], -1 191;CHECK: buffer_load_dword 192;CHECK: v_add_f32_e32 193;CHECK: s_mov_b64 exec, [[ORIG]] 194;CHECK: v_add_f32_e32 195define amdgpu_ps float @test_wwm3(i32 inreg %idx) { 196main_body: 197 ; use mbcnt to make sure the branch is divergent 198 %lo = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) 199 %hi = call i32 @llvm.amdgcn.mbcnt.hi(i32 -1, i32 %lo) 200 %cc = icmp uge i32 %hi, 32 201 br i1 %cc, label %endif, label %if 202 203if: 204 %src = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx, i32 0, i32 0, i32 0) 205 %out = fadd float %src, %src 206 %out.0 = call float @llvm.amdgcn.wwm.f32(float %out) 207 %out.1 = fadd float %src, %out.0 208 br label %endif 209 210endif: 211 %out.2 = phi float [ %out.1, %if ], [ 0.0, %main_body ] 212 ret float %out.2 213} 214 215; Check that WWM writes aren't coalesced with non-WWM writes, since the WWM 216; write could clobber disabled channels in the non-WWM one. 217; 218;CHECK-LABEL: {{^}}test_wwm4: 219;CHECK: s_or_saveexec_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], -1 220;CHECK: buffer_load_dword 221;CHECK: v_add_f32_e32 222;CHECK: s_mov_b64 exec, [[ORIG]] 223;CHECK-NEXT: v_mov_b32_e32 224define amdgpu_ps float @test_wwm4(i32 inreg %idx) { 225main_body: 226 ; use mbcnt to make sure the branch is divergent 227 %lo = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) 228 %hi = call i32 @llvm.amdgcn.mbcnt.hi(i32 -1, i32 %lo) 229 %cc = icmp uge i32 %hi, 32 230 br i1 %cc, label %endif, label %if 231 232if: 233 %src = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx, i32 0, i32 0, i32 0) 234 %out = fadd float %src, %src 235 %out.0 = call float @llvm.amdgcn.wwm.f32(float %out) 236 br label %endif 237 238endif: 239 %out.1 = phi float [ %out.0, %if ], [ 0.0, %main_body ] 240 ret float %out.1 241} 242 243; Make sure the transition from Exact to WWM then WQM works properly. 244; 245;CHECK-LABEL: {{^}}test_wwm5: 246;CHECK: buffer_load_dword 247;CHECK: buffer_store_dword 248;CHECK: s_or_saveexec_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], -1 249;CHECK: buffer_load_dword 250;CHECK: v_add_f32_e32 251;CHECK: s_mov_b64 exec, [[ORIG]] 252;CHECK: s_wqm_b64 exec, exec 253define amdgpu_ps float @test_wwm5(i32 inreg %idx0, i32 inreg %idx1) { 254main_body: 255 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 256 call void @llvm.amdgcn.struct.buffer.store.f32(float %src0, <4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 257 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 258 %temp = fadd float %src1, %src1 259 %temp.0 = call float @llvm.amdgcn.wwm.f32(float %temp) 260 %out = fadd float %temp.0, %temp.0 261 %out.0 = call float @llvm.amdgcn.wqm.f32(float %out) 262 ret float %out.0 263} 264 265; Check that WWM is turned on correctly across basic block boundaries. 266; if..then..endif version 267; 268;CHECK-LABEL: {{^}}test_wwm6_then: 269;CHECK: s_or_saveexec_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], -1 270;SI-CHECK: buffer_load_dword 271;VI-CHECK: flat_load_dword 272;CHECK: s_mov_b64 exec, [[ORIG]] 273;CHECK: %if 274;CHECK: s_or_saveexec_b64 [[ORIG2:s\[[0-9]+:[0-9]+\]]], -1 275;SI-CHECK: buffer_load_dword 276;VI-CHECK: flat_load_dword 277;CHECK: v_add_f32_e32 278;CHECK: s_mov_b64 exec, [[ORIG2]] 279define amdgpu_ps float @test_wwm6_then() { 280main_body: 281 %src0 = load volatile float, float addrspace(1)* undef 282 ; use mbcnt to make sure the branch is divergent 283 %lo = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) 284 %hi = call i32 @llvm.amdgcn.mbcnt.hi(i32 -1, i32 %lo) 285 %cc = icmp uge i32 %hi, 32 286 br i1 %cc, label %endif, label %if 287 288if: 289 %src1 = load volatile float, float addrspace(1)* undef 290 %out = fadd float %src0, %src1 291 %out.0 = call float @llvm.amdgcn.wwm.f32(float %out) 292 br label %endif 293 294endif: 295 %out.1 = phi float [ %out.0, %if ], [ 0.0, %main_body ] 296 ret float %out.1 297} 298 299; Check that WWM is turned on correctly across basic block boundaries. 300; loop version 301; 302;CHECK-LABEL: {{^}}test_wwm6_loop: 303;CHECK: s_or_saveexec_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], -1 304;SI-CHECK: buffer_load_dword 305;VI-CHECK: flat_load_dword 306;CHECK: s_mov_b64 exec, [[ORIG]] 307;CHECK: %loop 308;CHECK: s_or_saveexec_b64 [[ORIG2:s\[[0-9]+:[0-9]+\]]], -1 309;SI-CHECK: buffer_load_dword 310;VI-CHECK: flat_load_dword 311;CHECK: s_mov_b64 exec, [[ORIG2]] 312define amdgpu_ps float @test_wwm6_loop() { 313main_body: 314 %src0 = load volatile float, float addrspace(1)* undef 315 ; use mbcnt to make sure the branch is divergent 316 %lo = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) 317 %hi = call i32 @llvm.amdgcn.mbcnt.hi(i32 -1, i32 %lo) 318 br label %loop 319 320loop: 321 %counter = phi i32 [ %lo, %main_body ], [ %counter.1, %loop ] 322 %src1 = load volatile float, float addrspace(1)* undef 323 %out = fadd float %src0, %src1 324 %out.0 = call float @llvm.amdgcn.wwm.f32(float %out) 325 %counter.1 = sub i32 %counter, 1 326 %cc = icmp ne i32 %counter.1, 0 327 br i1 %cc, label %loop, label %endloop 328 329endloop: 330 ret float %out.0 331} 332 333; Check that @llvm.amdgcn.set.inactive disables WWM. 334; 335;CHECK-LABEL: {{^}}test_set_inactive1: 336;CHECK: buffer_load_dword 337;CHECK: s_not_b64 exec, exec 338;CHECK: v_mov_b32_e32 339;CHECK: s_not_b64 exec, exec 340;CHECK: s_or_saveexec_b64 s{{\[[0-9]+:[0-9]+\]}}, -1 341;CHECK: v_add_{{[iu]}}32_e32 342define amdgpu_ps void @test_set_inactive1(i32 inreg %idx) { 343main_body: 344 %src = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx, i32 0, i32 0, i32 0) 345 %src.0 = bitcast float %src to i32 346 %src.1 = call i32 @llvm.amdgcn.set.inactive.i32(i32 %src.0, i32 0) 347 %out = add i32 %src.1, %src.1 348 %out.0 = call i32 @llvm.amdgcn.wwm.i32(i32 %out) 349 %out.1 = bitcast i32 %out.0 to float 350 call void @llvm.amdgcn.struct.buffer.store.f32(float %out.1, <4 x i32> undef, i32 %idx, i32 0, i32 0, i32 0) 351 ret void 352} 353 354; Check that enabling WQM anywhere enables WQM for the set.inactive source. 355; 356;CHECK-LABEL: {{^}}test_set_inactive2: 357;CHECK: s_wqm_b64 exec, exec 358;CHECK: buffer_load_dword 359;CHECK: buffer_load_dword 360define amdgpu_ps void @test_set_inactive2(i32 inreg %idx0, i32 inreg %idx1) { 361main_body: 362 %src1 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 363 %src1.0 = bitcast float %src1 to i32 364 %src1.1 = call i32 @llvm.amdgcn.set.inactive.i32(i32 %src1.0, i32 undef) 365 %src0 = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx0, i32 0, i32 0, i32 0) 366 %src0.0 = bitcast float %src0 to i32 367 %src0.1 = call i32 @llvm.amdgcn.wqm.i32(i32 %src0.0) 368 %out = add i32 %src0.1, %src1.1 369 %out.0 = bitcast i32 %out to float 370 call void @llvm.amdgcn.struct.buffer.store.f32(float %out.0, <4 x i32> undef, i32 %idx1, i32 0, i32 0, i32 0) 371 ret void 372} 373 374; Check a case of one branch of an if-else requiring WQM, the other requiring 375; exact. 376; 377; Note: In this particular case, the save-and-restore could be avoided if the 378; analysis understood that the two branches of the if-else are mutually 379; exclusive. 380; 381;CHECK-LABEL: {{^}}test_control_flow_0: 382;CHECK-NEXT: ; %main_body 383;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 384;CHECK-NEXT: s_wqm_b64 exec, exec 385;CHECK: %ELSE 386;CHECK: s_and_saveexec_b64 [[SAVED:s\[[0-9]+:[0-9]+\]]], [[ORIG]] 387;CHECK: store 388;CHECK: s_mov_b64 exec, [[SAVED]] 389;CHECK: %IF 390;CHECK: image_sample 391;CHECK: image_sample 392define amdgpu_ps float @test_control_flow_0(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 %c, i32 %z, float %data) { 393main_body: 394 %cmp = icmp eq i32 %z, 0 395 br i1 %cmp, label %IF, label %ELSE 396 397IF: 398 %c.bc = bitcast i32 %c to float 399 %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 false, i32 0, i32 0) #0 400 %tex0 = extractelement <4 x float> %tex, i32 0 401 %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 false, i32 0, i32 0) #0 402 %data.if = extractelement <4 x float> %dtex, i32 0 403 br label %END 404 405ELSE: 406 call void @llvm.amdgcn.struct.buffer.store.f32(float %data, <4 x i32> undef, i32 %c, i32 0, i32 0, i32 0) 407 br label %END 408 409END: 410 %r = phi float [ %data.if, %IF ], [ %data, %ELSE ] 411 ret float %r 412} 413 414; Reverse branch order compared to the previous test. 415; 416;CHECK-LABEL: {{^}}test_control_flow_1: 417;CHECK-NEXT: ; %main_body 418;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 419;CHECK-NEXT: s_wqm_b64 exec, exec 420;CHECK: %IF 421;CHECK: image_sample 422;CHECK: image_sample 423;CHECK: %Flow 424;CHECK-NEXT: s_or_saveexec_b64 [[SAVED:s\[[0-9]+:[0-9]+\]]], 425;CHECK-NEXT: s_and_b64 exec, exec, [[ORIG]] 426;CHECK-NEXT: s_and_b64 [[SAVED]], exec, [[SAVED]] 427;CHECK-NEXT: s_xor_b64 exec, exec, [[SAVED]] 428;CHECK-NEXT: s_cbranch_execz [[END_BB:BB[0-9]+_[0-9]+]] 429;CHECK-NEXT: ; %bb.{{[0-9]+}}: ; %ELSE 430;CHECK: store_dword 431;CHECK: [[END_BB]]: ; %END 432;CHECK: s_or_b64 exec, exec, 433;CHECK: v_mov_b32_e32 v0 434;CHECK: ; return 435define amdgpu_ps float @test_control_flow_1(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 %c, i32 %z, float %data) { 436main_body: 437 %cmp = icmp eq i32 %z, 0 438 br i1 %cmp, label %ELSE, label %IF 439 440IF: 441 %c.bc = bitcast i32 %c to float 442 %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 false, i32 0, i32 0) #0 443 %tex0 = extractelement <4 x float> %tex, i32 0 444 %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 false, i32 0, i32 0) #0 445 %data.if = extractelement <4 x float> %dtex, i32 0 446 br label %END 447 448ELSE: 449 call void @llvm.amdgcn.struct.buffer.store.f32(float %data, <4 x i32> undef, i32 %c, i32 0, i32 0, i32 0) 450 br label %END 451 452END: 453 %r = phi float [ %data.if, %IF ], [ %data, %ELSE ] 454 ret float %r 455} 456 457; Check that branch conditions are properly marked as needing WQM... 458; 459;CHECK-LABEL: {{^}}test_control_flow_2: 460;CHECK-NEXT: ; %main_body 461;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 462;CHECK-NEXT: s_wqm_b64 exec, exec 463;CHECK: s_and_b64 exec, exec, [[ORIG]] 464;CHECK: store 465;CHECK: s_wqm_b64 exec, exec 466;CHECK: load 467;CHECK: s_and_b64 exec, exec, [[ORIG]] 468;CHECK: store 469;CHECK: s_wqm_b64 exec, exec 470;CHECK: v_cmp 471define amdgpu_ps <4 x float> @test_control_flow_2(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, <3 x i32> %idx, <2 x float> %data, i32 %coord) { 472main_body: 473 %idx.1 = extractelement <3 x i32> %idx, i32 0 474 %data.1 = extractelement <2 x float> %data, i32 0 475 call void @llvm.amdgcn.struct.buffer.store.f32(float %data.1, <4 x i32> undef, i32 %idx.1, i32 0, i32 0, i32 0) 476 477 ; The load that determines the branch (and should therefore be WQM) is 478 ; surrounded by stores that require disabled WQM. 479 %idx.2 = extractelement <3 x i32> %idx, i32 1 480 %z = call float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32> undef, i32 %idx.2, i32 0, i32 0, i32 0) 481 482 %idx.3 = extractelement <3 x i32> %idx, i32 2 483 %data.3 = extractelement <2 x float> %data, i32 1 484 call void @llvm.amdgcn.struct.buffer.store.f32(float %data.3, <4 x i32> undef, i32 %idx.3, i32 0, i32 0, i32 0) 485 486 %cc = fcmp ogt float %z, 0.0 487 br i1 %cc, label %IF, label %ELSE 488 489IF: 490 %coord.IF = mul i32 %coord, 3 491 br label %END 492 493ELSE: 494 %coord.ELSE = mul i32 %coord, 4 495 br label %END 496 497END: 498 %coord.END = phi i32 [ %coord.IF, %IF ], [ %coord.ELSE, %ELSE ] 499 %coord.END.bc = bitcast i32 %coord.END to float 500 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %coord.END.bc, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 501 ret <4 x float> %tex 502} 503 504; ... but only if they really do need it. 505; 506;CHECK-LABEL: {{^}}test_control_flow_3: 507;CHECK-NEXT: ; %main_body 508;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 509;CHECK-NEXT: s_wqm_b64 exec, exec 510;CHECK: image_sample 511;CHECK: s_and_b64 exec, exec, [[ORIG]] 512;CHECK: image_sample 513;CHECK-DAG: v_cmp 514;CHECK-DAG: store 515define amdgpu_ps float @test_control_flow_3(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 %idx, float %coord) { 516main_body: 517 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %coord, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 518 %tex0 = extractelement <4 x float> %tex, i32 0 519 %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 false, i32 0, i32 0) #0 520 %dtex.1 = extractelement <4 x float> %dtex, i32 0 521 call void @llvm.amdgcn.struct.buffer.store.f32(float %dtex.1, <4 x i32> undef, i32 %idx, i32 0, i32 0, i32 0) 522 523 %cc = fcmp ogt float %dtex.1, 0.0 524 br i1 %cc, label %IF, label %ELSE 525 526IF: 527 %tex.IF = fmul float %dtex.1, 3.0 528 br label %END 529 530ELSE: 531 %tex.ELSE = fmul float %dtex.1, 4.0 532 br label %END 533 534END: 535 %tex.END = phi float [ %tex.IF, %IF ], [ %tex.ELSE, %ELSE ] 536 ret float %tex.END 537} 538 539; Another test that failed at some point because of terminator handling. 540; 541;CHECK-LABEL: {{^}}test_control_flow_4: 542;CHECK-NEXT: ; %main_body 543;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 544;CHECK-NEXT: s_wqm_b64 exec, exec 545;CHECK: %IF 546;CHECK: s_and_saveexec_b64 [[SAVE:s\[[0-9]+:[0-9]+\]]], [[ORIG]] 547;CHECK: load 548;CHECK: store 549;CHECK: s_mov_b64 exec, [[SAVE]] 550;CHECK: %END 551;CHECK: image_sample 552;CHECK: image_sample 553define amdgpu_ps <4 x float> @test_control_flow_4(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, float %coord, i32 %y, float %z) { 554main_body: 555 %cond = icmp eq i32 %y, 0 556 br i1 %cond, label %IF, label %END 557 558IF: 559 %data = call float @llvm.amdgcn.raw.buffer.load.f32(<4 x i32> undef, i32 0, i32 0, i32 0) 560 call void @llvm.amdgcn.struct.buffer.store.f32(float %data, <4 x i32> undef, i32 1, i32 0, i32 0, i32 0) 561 br label %END 562 563END: 564 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %coord, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 565 %tex0 = extractelement <4 x float> %tex, i32 0 566 %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 false, i32 0, i32 0) #0 567 ret <4 x float> %dtex 568} 569 570; Kill is performed in WQM mode so that uniform kill behaves correctly ... 571; 572;CHECK-LABEL: {{^}}test_kill_0: 573;CHECK-NEXT: ; %main_body 574;CHECK-NEXT: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 575;CHECK-NEXT: s_wqm_b64 exec, exec 576;CHECK: s_and_b64 exec, exec, [[ORIG]] 577;CHECK: image_sample 578;CHECK: buffer_store_dword 579;CHECK: s_wqm_b64 exec, exec 580;CHECK: v_cmpx_ 581;CHECK: s_and_saveexec_b64 [[SAVE:s\[[0-9]+:[0-9]+\]]], [[ORIG]] 582;CHECK: buffer_store_dword 583;CHECK: s_mov_b64 exec, [[SAVE]] 584;CHECK: image_sample 585define amdgpu_ps <4 x float> @test_kill_0(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, float addrspace(1)* inreg %ptr, <2 x i32> %idx, <2 x float> %data, float %coord, float %coord2, float %z) { 586main_body: 587 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %coord, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 588 %idx.0 = extractelement <2 x i32> %idx, i32 0 589 %data.0 = extractelement <2 x float> %data, i32 0 590 call void @llvm.amdgcn.struct.buffer.store.f32(float %data.0, <4 x i32> undef, i32 %idx.0, i32 0, i32 0, i32 0) 591 592 %z.cmp = fcmp olt float %z, 0.0 593 call void @llvm.amdgcn.kill(i1 %z.cmp) 594 595 %idx.1 = extractelement <2 x i32> %idx, i32 1 596 %data.1 = extractelement <2 x float> %data, i32 1 597 call void @llvm.amdgcn.struct.buffer.store.f32(float %data.1, <4 x i32> undef, i32 %idx.1, i32 0, i32 0, i32 0) 598 %tex2 = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %coord2, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 599 %tex2.0 = extractelement <4 x float> %tex2, i32 0 600 %dtex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %tex2.0, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 601 %out = fadd <4 x float> %tex, %dtex 602 603 ret <4 x float> %out 604} 605 606; ... but only if WQM is necessary. 607; 608; CHECK-LABEL: {{^}}test_kill_1: 609; CHECK-NEXT: ; %main_body 610; CHECK: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 611; CHECK: s_wqm_b64 exec, exec 612; CHECK: image_sample 613; CHECK: s_and_b64 exec, exec, [[ORIG]] 614; CHECK: image_sample 615; CHECK: buffer_store_dword 616; CHECK-NOT: wqm 617; CHECK: v_cmpx_ 618define amdgpu_ps <4 x float> @test_kill_1(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 %idx, float %data, float %coord, float %coord2, float %z) { 619main_body: 620 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %coord, <8 x i32> %rsrc, <4 x i32> %sampler, i1 false, i32 0, i32 0) #0 621 %tex0 = extractelement <4 x float> %tex, i32 0 622 %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 false, i32 0, i32 0) #0 623 624 call void @llvm.amdgcn.raw.buffer.store.f32(float %data, <4 x i32> undef, i32 0, i32 0, i32 0) 625 626 %z.cmp = fcmp olt float %z, 0.0 627 call void @llvm.amdgcn.kill(i1 %z.cmp) 628 629 ret <4 x float> %dtex 630} 631 632; Check prolog shaders. 633; 634; CHECK-LABEL: {{^}}test_prolog_1: 635; CHECK: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 636; CHECK: s_wqm_b64 exec, exec 637; CHECK: v_add_f32_e32 v0, 638; CHECK: s_and_b64 exec, exec, [[ORIG]] 639define amdgpu_ps float @test_prolog_1(float %a, float %b) #5 { 640main_body: 641 %s = fadd float %a, %b 642 ret float %s 643} 644 645; CHECK-LABEL: {{^}}test_loop_vcc: 646; CHECK-NEXT: ; %entry 647; CHECK-NEXT: s_mov_b64 [[LIVE:s\[[0-9]+:[0-9]+\]]], exec 648; CHECK: s_wqm_b64 exec, exec 649; CHECK: s_and_b64 exec, exec, [[LIVE]] 650; CHECK: image_store 651; CHECK: s_wqm_b64 exec, exec 652; CHECK-DAG: v_mov_b32_e32 [[CTR:v[0-9]+]], 0 653; CHECK-DAG: s_mov_b32 [[SEVEN:s[0-9]+]], 0x40e00000 654 655; CHECK: [[LOOPHDR:BB[0-9]+_[0-9]+]]: ; %loop 656; CHECK: v_cmp_lt_f32_e32 vcc, [[SEVEN]], [[CTR]] 657; CHECK: s_cbranch_vccnz 658 659; CHECK: ; %body 660; CHECK: v_add_f32_e32 [[CTR]], 2.0, [[CTR]] 661; CHECK: s_branch [[LOOPHDR]] 662 663; CHECK: ; %break 664; CHECK: ; return 665define amdgpu_ps <4 x float> @test_loop_vcc(<4 x float> %in) nounwind { 666entry: 667 call void @llvm.amdgcn.image.store.1d.v4f32.i32(<4 x float> %in, i32 15, i32 undef, <8 x i32> undef, i32 0, i32 0) 668 br label %loop 669 670loop: 671 %ctr.iv = phi float [ 0.0, %entry ], [ %ctr.next, %body ] 672 %c.iv = phi <4 x float> [ %in, %entry ], [ %c.next, %body ] 673 %cc = fcmp ogt float %ctr.iv, 7.0 674 br i1 %cc, label %break, label %body 675 676body: 677 %c.iv0 = extractelement <4 x float> %c.iv, i32 0 678 %c.next = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %c.iv0, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 679 %ctr.next = fadd float %ctr.iv, 2.0 680 br label %loop 681 682break: 683 ret <4 x float> %c.iv 684} 685 686; Only intrinsic stores need exact execution -- other stores do not have 687; externally visible effects and may require WQM for correctness. 688; 689; CHECK-LABEL: {{^}}test_alloca: 690; CHECK: s_mov_b64 [[LIVE:s\[[0-9]+:[0-9]+\]]], exec 691; CHECK: s_wqm_b64 exec, exec 692 693; CHECK: s_and_b64 exec, exec, [[LIVE]] 694; CHECK: buffer_store_dword {{v[0-9]+}}, off, {{s\[[0-9]+:[0-9]+\]}}, 0 695; CHECK: s_wqm_b64 exec, exec 696; CHECK: buffer_store_dword {{v[0-9]+}}, off, {{s\[[0-9]+:[0-9]+\]}}, {{s[0-9]+}} offset:4{{$}} 697; CHECK: s_and_b64 exec, exec, [[LIVE]] 698; CHECK: buffer_store_dword {{v[0-9]+}}, {{v[0-9]+}}, {{s\[[0-9]+:[0-9]+\]}}, 0 idxen 699; CHECK: s_wqm_b64 exec, exec 700; CHECK: buffer_load_dword {{v[0-9]+}}, {{v[0-9]+}}, {{s\[[0-9]+:[0-9]+\]}}, {{s[0-9]+}} offen 701 702; CHECK: s_and_b64 exec, exec, [[LIVE]] 703; CHECK: image_sample 704; CHECK: buffer_store_dwordx4 705define amdgpu_ps void @test_alloca(float %data, i32 %a, i32 %idx) nounwind { 706entry: 707 %array = alloca [32 x i32], align 4, addrspace(5) 708 709 call void @llvm.amdgcn.raw.buffer.store.f32(float %data, <4 x i32> undef, i32 0, i32 0, i32 0) 710 711 %s.gep = getelementptr [32 x i32], [32 x i32] addrspace(5)* %array, i32 0, i32 0 712 store volatile i32 %a, i32 addrspace(5)* %s.gep, align 4 713 714 call void @llvm.amdgcn.struct.buffer.store.f32(float %data, <4 x i32> undef, i32 1, i32 0, i32 0, i32 0) 715 716 %c.gep = getelementptr [32 x i32], [32 x i32] addrspace(5)* %array, i32 0, i32 %idx 717 %c = load i32, i32 addrspace(5)* %c.gep, align 4 718 %c.bc = bitcast i32 %c to float 719 %t = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %c.bc, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 720 call void @llvm.amdgcn.raw.buffer.store.v4f32(<4 x float> %t, <4 x i32> undef, i32 0, i32 0, i32 0) 721 722 ret void 723} 724 725; Must return to exact at the end of a non-void returning shader, 726; otherwise the EXEC mask exported by the epilog will be wrong. This is true 727; even if the shader has no kills, because a kill could have happened in a 728; previous shader fragment. 729; 730; CHECK-LABEL: {{^}}test_nonvoid_return: 731; CHECK: s_mov_b64 [[LIVE:s\[[0-9]+:[0-9]+\]]], exec 732; CHECK: s_wqm_b64 exec, exec 733; 734; CHECK: s_and_b64 exec, exec, [[LIVE]] 735; CHECK-NOT: exec 736define amdgpu_ps <4 x float> @test_nonvoid_return() nounwind { 737 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float undef, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 738 %tex0 = extractelement <4 x float> %tex, i32 0 739 %dtex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %tex0, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 740 ret <4 x float> %dtex 741} 742 743; CHECK-LABEL: {{^}}test_nonvoid_return_unreachable: 744; CHECK: s_mov_b64 [[LIVE:s\[[0-9]+:[0-9]+\]]], exec 745; CHECK: s_wqm_b64 exec, exec 746; 747; CHECK: s_and_b64 exec, exec, [[LIVE]] 748; CHECK-NOT: exec 749define amdgpu_ps <4 x float> @test_nonvoid_return_unreachable(i32 inreg %c) nounwind { 750entry: 751 %tex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float undef, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 752 %tex0 = extractelement <4 x float> %tex, i32 0 753 %dtex = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float %tex0, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 754 %cc = icmp sgt i32 %c, 0 755 br i1 %cc, label %if, label %else 756 757if: 758 store volatile <4 x float> %dtex, <4 x float> addrspace(1)* undef 759 unreachable 760 761else: 762 ret <4 x float> %dtex 763} 764 765; Test awareness that s_wqm_b64 clobbers SCC. 766; 767; CHECK-LABEL: {{^}}test_scc: 768; CHECK: s_mov_b64 [[ORIG:s\[[0-9]+:[0-9]+\]]], exec 769; CHECK: s_wqm_b64 exec, exec 770; CHECK: s_cmp_ 771; CHECK-NEXT: s_cbranch_scc 772; CHECK: ; %if 773; CHECK: s_and_b64 exec, exec, [[ORIG]] 774; CHECK: image_sample 775; CHECK: ; %else 776; CHECK: s_and_b64 exec, exec, [[ORIG]] 777; CHECK: image_sample 778; CHECK: ; %end 779define amdgpu_ps <4 x float> @test_scc(i32 inreg %sel, i32 %idx) #1 { 780main_body: 781 %cc = icmp sgt i32 %sel, 0 782 br i1 %cc, label %if, label %else 783 784if: 785 %r.if = call <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32 15, float 0.0, <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 786 br label %end 787 788else: 789 %r.else = call <4 x float> @llvm.amdgcn.image.sample.2d.v4f32.f32(i32 15, float 0.0, float bitcast (i32 1 to float), <8 x i32> undef, <4 x i32> undef, i1 false, i32 0, i32 0) #0 790 br label %end 791 792end: 793 %r = phi <4 x float> [ %r.if, %if ], [ %r.else, %else ] 794 call void @llvm.amdgcn.struct.buffer.store.f32(float 1.0, <4 x i32> undef, i32 %idx, i32 0, i32 0, i32 0) 795 ret <4 x float> %r 796} 797 798; Check a case of a block being entirely WQM except for a bit of WWM. 799; There was a bug where it forgot to enter and leave WWM. 800; 801;CHECK-LABEL: {{^}}test_wwm_within_wqm: 802;CHECK: %IF 803;CHECK: s_or_saveexec_b64 {{.*}}, -1 804;CHECK: ds_swizzle 805; 806define amdgpu_ps float @test_wwm_within_wqm(<8 x i32> inreg %rsrc, <4 x i32> inreg %sampler, i32 %c, i32 %z, float %data) { 807main_body: 808 %c.bc = bitcast i32 %c to float 809 %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 false, i32 0, i32 0) #0 810 %tex0 = extractelement <4 x float> %tex, i32 0 811 %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 false, i32 0, i32 0) #0 812 %cmp = icmp eq i32 %z, 0 813 br i1 %cmp, label %IF, label %ENDIF 814 815IF: 816 %dataf = extractelement <4 x float> %dtex, i32 0 817 %data1 = fptosi float %dataf to i32 818 %data2 = call i32 @llvm.amdgcn.set.inactive.i32(i32 %data1, i32 0) 819 %data3 = call i32 @llvm.amdgcn.ds.swizzle(i32 %data2, i32 2079) 820 %data4 = call i32 @llvm.amdgcn.wwm.i32(i32 %data3) 821 %data4f = sitofp i32 %data4 to float 822 br label %ENDIF 823 824ENDIF: 825 %r = phi float [ %data4f, %IF ], [ 0.0, %main_body ] 826 ret float %r 827} 828 829declare void @llvm.amdgcn.exp.f32(i32, i32, float, float, float, float, i1, i1) #1 830declare void @llvm.amdgcn.image.store.1d.v4f32.i32(<4 x float>, i32, i32, <8 x i32>, i32, i32) #1 831 832declare void @llvm.amdgcn.struct.buffer.store.f32(float, <4 x i32>, i32, i32, i32, i32 immarg) #2 833declare void @llvm.amdgcn.struct.buffer.store.v4f32(<4 x float>, <4 x i32>, i32, i32, i32, i32 immarg) #2 834declare void @llvm.amdgcn.raw.buffer.store.v4f32(<4 x float>, <4 x i32>, i32, i32, i32 immarg) #2 835declare void @llvm.amdgcn.raw.buffer.store.f32(float, <4 x i32>, i32, i32, i32 immarg) #2 836declare float @llvm.amdgcn.raw.buffer.load.f32(<4 x i32>, i32, i32, i32) #3 837declare float @llvm.amdgcn.struct.buffer.load.f32(<4 x i32>, i32, i32, i32, i32) #3 838 839declare <4 x float> @llvm.amdgcn.image.load.1d.v4f32.i32(i32, i32, <8 x i32>, i32, i32) #3 840declare <4 x float> @llvm.amdgcn.image.sample.1d.v4f32.f32(i32, float, <8 x i32>, <4 x i32>, i1, i32, i32) #3 841declare <4 x float> @llvm.amdgcn.image.sample.2d.v4f32.f32(i32, float, float, <8 x i32>, <4 x i32>, i1, i32, i32) #3 842declare void @llvm.amdgcn.kill(i1) #1 843declare float @llvm.amdgcn.wqm.f32(float) #3 844declare i32 @llvm.amdgcn.wqm.i32(i32) #3 845declare float @llvm.amdgcn.wwm.f32(float) #3 846declare i32 @llvm.amdgcn.wwm.i32(i32) #3 847declare i32 @llvm.amdgcn.set.inactive.i32(i32, i32) #4 848declare i32 @llvm.amdgcn.mbcnt.lo(i32, i32) #3 849declare i32 @llvm.amdgcn.mbcnt.hi(i32, i32) #3 850declare <2 x half> @llvm.amdgcn.cvt.pkrtz(float, float) #3 851declare void @llvm.amdgcn.exp.compr.v2f16(i32, i32, <2 x half>, <2 x half>, i1, i1) #1 852declare float @llvm.amdgcn.interp.p1(float, i32, i32, i32) #2 853declare float @llvm.amdgcn.interp.p2(float, float, i32, i32, i32) #2 854declare i32 @llvm.amdgcn.ds.swizzle(i32, i32) 855 856attributes #1 = { nounwind } 857attributes #2 = { nounwind readonly } 858attributes #3 = { nounwind readnone } 859attributes #4 = { nounwind readnone convergent } 860attributes #5 = { "amdgpu-ps-wqm-outputs" } 861attributes #6 = { nounwind "InitialPSInputAddr"="2" } 862