233 lines · plain
1; RUN: opt -S -dxil-op-lower %s | FileCheck %s2 3target triple = "dxil-pc-shadermodel6.6-compute"4 5declare void @scalar_user(float)6declare void @vector_user(<4 x float>)7declare void @check_user(i1)8 9define void @loadv4f32() {10 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,11 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]12 %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)13 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_0_0_0(14 i32 0, i32 0, i32 1, i32 0, ptr null)15 16 ; The temporary casts should all have been cleaned up17 ; CHECK-NOT: %dx.resource.casthandle18 19 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR:]]20 %load0 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(21 target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 0)22 %data0 = extractvalue {<4 x float>, i1} %load0, 023 24 ; The extract order depends on the users, so don't enforce that here.25 ; CHECK-DAG: [[VAL0_0:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 026 %data0_0 = extractelement <4 x float> %data0, i32 027 ; CHECK-DAG: [[VAL0_2:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 228 %data0_2 = extractelement <4 x float> %data0, i32 229 30 ; If all of the uses are extracts, we skip creating a vector31 ; CHECK-NOT: insertelement32 ; CHECK-DAG: call void @scalar_user(float [[VAL0_0]])33 ; CHECK-DAG: call void @scalar_user(float [[VAL0_2]])34 call void @scalar_user(float %data0_0)35 call void @scalar_user(float %data0_2)36 37 ; CHECK: [[DATA4:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 4, i32 undef) #[[#ATTR]]38 %load4 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(39 target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 4)40 %data4 = extractvalue {<4 x float>, i1} %load4, 041 42 ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 043 ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 144 ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 245 ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 346 ; CHECK: insertelement <4 x float> poison47 ; CHECK: insertelement <4 x float>48 ; CHECK: insertelement <4 x float>49 ; CHECK: insertelement <4 x float>50 call void @vector_user(<4 x float> %data4)51 52 ; CHECK: [[DATA12:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 12, i32 undef) #[[#ATTR]]53 %load12 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(54 target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 12)55 %data12 = extractvalue {<4 x float>, i1} %load12, 056 57 ; CHECK: [[DATA12_3:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA12]], 358 %data12_3 = extractelement <4 x float> %data12, i32 359 60 ; If there are a mix of users we need the vector, but extracts are direct61 ; CHECK: call void @scalar_user(float [[DATA12_3]])62 call void @scalar_user(float %data12_3)63 call void @vector_user(<4 x float> %data12)64 65 ret void66}67 68define void @index_dynamic(i32 %bufindex, i32 %elemindex) {69 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,70 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]71 %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)72 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_0_0_0(73 i32 0, i32 0, i32 1, i32 0, ptr null)74 75 ; CHECK: [[LOAD:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 %bufindex, i32 undef) #[[#ATTR]]76 %load = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(77 target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %bufindex)78 %data = extractvalue {<4 x float>, i1} %load, 079 80 ; CHECK: [[ALLOCA:%.*]] = alloca [4 x float]81 ; CHECK: [[V0:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 082 ; CHECK: [[A0:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 083 ; CHECK: store float [[V0]], ptr [[A0]]84 ; CHECK: [[V1:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 185 ; CHECK: [[A1:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 186 ; CHECK: store float [[V1]], ptr [[A1]]87 ; CHECK: [[V2:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 288 ; CHECK: [[A2:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 289 ; CHECK: store float [[V2]], ptr [[A2]]90 ; CHECK: [[V3:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 391 ; CHECK: [[A3:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 392 ; CHECK: store float [[V3]], ptr [[A3]]93 ;94 ; CHECK: [[PTR:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 %elemindex95 ; CHECK: [[X:%.*]] = load float, ptr [[PTR]]96 %x = extractelement <4 x float> %data, i32 %elemindex97 98 ; CHECK: call void @scalar_user(float [[X]])99 call void @scalar_user(float %x)100 101 ret void102}103 104define void @loadf32() {105 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,106 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]107 %buffer = call target("dx.TypedBuffer", float, 0, 0, 0)108 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_0_0_0(109 i32 0, i32 0, i32 1, i32 0, ptr null)110 111 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]112 %load0 = call {float, i1} @llvm.dx.resource.load.typedbuffer(113 target("dx.TypedBuffer", float, 0, 0, 0) %buffer, i32 0)114 %data0 = extractvalue {float, i1} %load0, 0115 116 ; CHECK: [[VAL0:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 0117 ; CHECK: call void @scalar_user(float [[VAL0]])118 call void @scalar_user(float %data0)119 120 ret void121}122 123define void @loadv2f32() {124 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,125 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]126 %buffer = call target("dx.TypedBuffer", <2 x float>, 0, 0, 0)127 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_0_0_0(128 i32 0, i32 0, i32 1, i32 0, ptr null)129 130 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]131 %data0 = call {<2 x float>, i1} @llvm.dx.resource.load.typedbuffer(132 target("dx.TypedBuffer", <2 x float>, 0, 0, 0) %buffer, i32 0)133 134 ret void135}136 137define void @loadv4f32_checkbit() {138 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,139 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]140 %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)141 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_0_0_0(142 i32 0, i32 0, i32 1, i32 0, ptr null)143 144 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]145 %data0 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer.f32(146 target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 0)147 148 ; CHECK: [[STATUS:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 4149 ; CHECK: [[MAPPED:%.*]] = call i1 @dx.op.checkAccessFullyMapped.i32(i32 71, i32 [[STATUS]]) #[[#ATTR]]150 %check = extractvalue {<4 x float>, i1} %data0, 1151 152 ; CHECK: call void @check_user(i1 [[MAPPED]])153 call void @check_user(i1 %check)154 155 ret void156}157 158define void @loadv4i32() {159 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,160 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]161 %buffer = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)162 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i32_0_0_0(163 i32 0, i32 0, i32 1, i32 0, ptr null)164 165 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]166 %data0 = call {<4 x i32>, i1} @llvm.dx.resource.load.typedbuffer(167 target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) %buffer, i32 0)168 169 ret void170}171 172define void @loadv4f16() {173 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,174 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]175 %buffer = call target("dx.TypedBuffer", <4 x half>, 0, 0, 0)176 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_0_0_0(177 i32 0, i32 0, i32 1, i32 0, ptr null)178 179 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f16 @dx.op.bufferLoad.f16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]180 %data0 = call {<4 x half>, i1} @llvm.dx.resource.load.typedbuffer(181 target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %buffer, i32 0)182 183 ret void184}185 186define void @loadv4i16() {187 ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,188 ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]189 %buffer = call target("dx.TypedBuffer", <4 x i16>, 0, 0, 0)190 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i16_0_0_0(191 i32 0, i32 0, i32 1, i32 0, ptr null)192 193 ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i16 @dx.op.bufferLoad.i16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]194 %data0 = call {<4 x i16>, i1} @llvm.dx.resource.load.typedbuffer(195 target("dx.TypedBuffer", <4 x i16>, 0, 0, 0) %buffer, i32 0)196 197 ret void198}199 200define void @loadf64() {201 ; show dxil op lower can handle typedbuffer load where target is double but load type is <2 x i32>202 ; CHECK: [[B1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 1, i32 0, i8 1 }, i32 1, i1 false) #0203 %buffer = call target("dx.TypedBuffer", double, 1, 0, 0)204 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_1_0_0t(205 i32 0, i32 1, i32 1, i32 0, ptr null)206 207 ; CHECK: [[BA:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[B1]], %dx.types.ResourceProperties { i32 4106, i32 266 }) #0208 %load = call { <2 x i32>, i1 } @llvm.dx.resource.load.typedbuffer(209 target("dx.TypedBuffer", double, 1, 0, 0) %buffer, i32 0)210 211; CHECK: call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle [[BA]], i32 0, i32 undef) #1212 %val = extractvalue { <2 x i32>, i1 } %load, 0213 ret void214}215 216define void @loadv2f64() {217 ; show dxil op lower can handle typedbuffer load where target is double2 but load type is <4 x i32>218 ; CHECK: [[B1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 1, i32 1, i32 0, i8 1 }, i32 1, i1 false) #0219 %buffer = call target("dx.TypedBuffer", <2 x double>, 1, 0, 0)220 @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f64_1_0_0t(221 i32 0, i32 1, i32 1, i32 0, ptr null)222 223 ; CHECK: [[BA:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[B1]], %dx.types.ResourceProperties { i32 4106, i32 522 }) #0224 %load = call { <4 x i32>, i1 } @llvm.dx.resource.load.typedbuffer(225 target("dx.TypedBuffer", <2 x double>, 1, 0, 0) %buffer, i32 0)226 227 ; CHECK: call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle [[BA]], i32 0, i32 undef) #1228 %val = extractvalue { <4 x i32>, i1 } %load, 0229 ret void230}231 232; CHECK: attributes #[[#ATTR]] = {{{.*}} memory(read) {{.*}}}233