Skip to content

Commit 6e2dae6

Browse files
FznamznonAlexeySotkin
authored andcommitted
Fix SPIRV friendly IR for OpImageSampleExplicitLod&OpSampledImage (#984)
These instructions were translated directly to OCL even if SPIR-V friendly LLVM IR was requested.
1 parent d5e7c5f commit 6e2dae6

File tree

6 files changed

+98
-71
lines changed

6 files changed

+98
-71
lines changed

lib/SPIRV/SPIRVReader.cpp

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ bool SPIRVToLLVM::isDirectlyTranslatedToOCL(Op OpCode) const {
690690
if (isSubgroupAvcINTELInstructionOpCode(OpCode) ||
691691
isIntelSubgroupOpCode(OpCode))
692692
return true;
693+
if (OpCode == OpImageSampleExplicitLod || OpCode == OpSampledImage)
694+
return false;
693695
if (OCLSPIRVBuiltinMap::rfind(OpCode, nullptr)) {
694696
// Not every spirv opcode which is placed in OCLSPIRVBuiltinMap is
695697
// translated directly to OCL builtin. Some of them are translated
@@ -1280,60 +1282,6 @@ static char getTypeSuffix(Type *T) {
12801282
return Suffix;
12811283
}
12821284

1283-
// ToDo: Handle unsigned integer return type. May need spec change.
1284-
Instruction *SPIRVToLLVM::postProcessOCLReadImage(SPIRVInstruction *BI,
1285-
CallInst *CI,
1286-
const std::string &FuncName) {
1287-
assert(CI->getCalledFunction() && "Unexpected indirect call");
1288-
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
1289-
StringRef ImageTypeName;
1290-
bool IsDepthImage = false;
1291-
if (isOCLImageType(
1292-
(cast<CallInst>(CI->getOperand(0)))->getArgOperand(0)->getType(),
1293-
&ImageTypeName))
1294-
IsDepthImage = ImageTypeName.contains("_depth_");
1295-
return mutateCallInstOCL(
1296-
M, CI,
1297-
[=](CallInst *, std::vector<Value *> &Args, llvm::Type *&RetTy) {
1298-
CallInst *CallSampledImg = cast<CallInst>(Args[0]);
1299-
auto Img = CallSampledImg->getArgOperand(0);
1300-
assert(isOCLImageType(Img->getType()));
1301-
auto Sampler = CallSampledImg->getArgOperand(1);
1302-
Args[0] = Img;
1303-
Args.insert(Args.begin() + 1, Sampler);
1304-
if (Args.size() > 4) {
1305-
ConstantInt *ImOp = dyn_cast<ConstantInt>(Args[3]);
1306-
ConstantFP *LodVal = dyn_cast<ConstantFP>(Args[4]);
1307-
// Drop "Image Operands" argument.
1308-
Args.erase(Args.begin() + 3, Args.begin() + 4);
1309-
// If the image operand is LOD and its value is zero, drop it too.
1310-
if (ImOp && LodVal && LodVal->isNullValue() &&
1311-
ImOp->getZExtValue() == ImageOperandsMask::ImageOperandsLodMask)
1312-
Args.erase(Args.begin() + 3, Args.end());
1313-
}
1314-
if (CallSampledImg->hasOneUse()) {
1315-
CallSampledImg->replaceAllUsesWith(
1316-
UndefValue::get(CallSampledImg->getType()));
1317-
CallSampledImg->dropAllReferences();
1318-
CallSampledImg->eraseFromParent();
1319-
}
1320-
Type *T = CI->getType();
1321-
if (auto VT = dyn_cast<VectorType>(T))
1322-
T = VT->getElementType();
1323-
RetTy = IsDepthImage ? T : CI->getType();
1324-
return std::string(kOCLBuiltinName::SampledReadImage) +
1325-
getTypeSuffix(T);
1326-
},
1327-
[=](CallInst *NewCI) -> Instruction * {
1328-
if (IsDepthImage)
1329-
return InsertElementInst::Create(
1330-
UndefValue::get(FixedVectorType::get(NewCI->getType(), 4)), NewCI,
1331-
getSizet(M, 0), "", NewCI->getParent());
1332-
return NewCI;
1333-
},
1334-
&Attrs);
1335-
}
1336-
13371285
CallInst *
13381286
SPIRVToLLVM::postProcessOCLWriteImage(SPIRVInstruction *BI, CallInst *CI,
13391287
const std::string &DemangledName) {
@@ -3050,8 +2998,6 @@ SPIRVToLLVM::transOCLBuiltinPostproc(SPIRVInstruction *BI, CallInst *CI,
30502998
return CastInst::Create(Instruction::Trunc, CI, transType(BI->getType()),
30512999
"cvt", BB);
30523000
}
3053-
if (OC == OpImageSampleExplicitLod)
3054-
return postProcessOCLReadImage(BI, CI, DemangledName);
30553001
if (OC == OpImageWrite) {
30563002
return postProcessOCLWriteImage(BI, CI, DemangledName);
30573003
}
@@ -3428,6 +3374,9 @@ Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI,
34283374
IsRetSigned = true;
34293375
}
34303376

3377+
if (OC == OpImageSampleExplicitLod)
3378+
AddRetTypePostfix = true;
3379+
34313380
if (AddRetTypePostfix) {
34323381
const Type *RetTy =
34333382
BI->hasType() ? transType(BI->getType()) : Type::getVoidTy(*Context);

lib/SPIRV/SPIRVReader.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,6 @@ class SPIRVToLLVM {
143143
bool postProcessOCLBuiltinWithArrayArguments(Function *F,
144144
StringRef DemangledName);
145145

146-
/// \brief Post-process OpImageSampleExplicitLod.
147-
/// sampled_image = __spirv_SampledImage__(image, sampler);
148-
/// return __spirv_ImageSampleExplicitLod__(sampled_image, image_operands,
149-
/// ...);
150-
/// =>
151-
/// read_image(image, sampler, ...)
152-
/// \return transformed call instruction.
153-
Instruction *postProcessOCLReadImage(SPIRVInstruction *BI, CallInst *CI,
154-
const std::string &DemangledName);
155-
156146
/// \brief Post-process OpImageWrite.
157147
/// return write_image(image, coord, color, image_operands, ...);
158148
/// =>

lib/SPIRV/SPIRVToOCL.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ void SPIRVToOCL::visitCallInst(CallInst &CI) {
101101
visitCallGroupWaitEvents(&CI, OC);
102102
return;
103103
}
104+
if (OC == OpImageSampleExplicitLod) {
105+
visitCallSPIRVImageSampleExplicitLodBuiltIn(&CI, OC);
106+
return;
107+
}
104108
if (OCLSPIRVBuiltinMap::rfind(OC))
105109
visitCallSPIRVBuiltin(&CI, OC);
106110
}
@@ -563,6 +567,77 @@ void SPIRVToOCL::visitCallGroupWaitEvents(CallInst *CI, Op OC) {
563567
&Attrs);
564568
}
565569

570+
static char getTypeSuffix(Type *T) {
571+
char Suffix;
572+
573+
Type *ST = T->getScalarType();
574+
if (ST->isHalfTy())
575+
Suffix = 'h';
576+
else if (ST->isFloatTy())
577+
Suffix = 'f';
578+
else
579+
Suffix = 'i';
580+
581+
return Suffix;
582+
}
583+
584+
// TODO: Handle unsigned integer return type. May need spec change.
585+
void SPIRVToOCL::visitCallSPIRVImageSampleExplicitLodBuiltIn(CallInst *CI,
586+
Op OC) {
587+
assert(CI->getCalledFunction() && "Unexpected indirect call");
588+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
589+
StringRef ImageTypeName;
590+
bool IsDepthImage = false;
591+
if (isOCLImageType(
592+
(cast<CallInst>(CI->getOperand(0)))->getArgOperand(0)->getType(),
593+
&ImageTypeName))
594+
IsDepthImage = ImageTypeName.contains("_depth_");
595+
596+
auto ModifyArguments = [=](CallInst *, std::vector<Value *> &Args,
597+
llvm::Type *&RetTy) {
598+
CallInst *CallSampledImg = cast<CallInst>(Args[0]);
599+
auto Img = CallSampledImg->getArgOperand(0);
600+
assert(isOCLImageType(Img->getType()));
601+
auto Sampler = CallSampledImg->getArgOperand(1);
602+
Args[0] = Img;
603+
Args.insert(Args.begin() + 1, Sampler);
604+
if (Args.size() > 4) {
605+
ConstantInt *ImOp = dyn_cast<ConstantInt>(Args[3]);
606+
ConstantFP *LodVal = dyn_cast<ConstantFP>(Args[4]);
607+
// Drop "Image Operands" argument.
608+
Args.erase(Args.begin() + 3, Args.begin() + 4);
609+
// If the image operand is LOD and its value is zero, drop it too.
610+
if (ImOp && LodVal && LodVal->isNullValue() &&
611+
ImOp->getZExtValue() == ImageOperandsMask::ImageOperandsLodMask)
612+
Args.erase(Args.begin() + 3, Args.end());
613+
}
614+
if (CallSampledImg->hasOneUse()) {
615+
CallSampledImg->replaceAllUsesWith(
616+
UndefValue::get(CallSampledImg->getType()));
617+
CallSampledImg->dropAllReferences();
618+
CallSampledImg->eraseFromParent();
619+
}
620+
Type *T = CI->getType();
621+
if (auto VT = dyn_cast<VectorType>(T))
622+
T = VT->getElementType();
623+
RetTy = IsDepthImage ? T : CI->getType();
624+
return std::string(kOCLBuiltinName::SampledReadImage) + getTypeSuffix(T);
625+
};
626+
627+
auto ModifyRetTy = [=](CallInst *NewCI) -> Instruction * {
628+
if (IsDepthImage) {
629+
auto Ins = InsertElementInst::Create(
630+
UndefValue::get(FixedVectorType::get(NewCI->getType(), 4)), NewCI,
631+
getSizet(M, 0));
632+
Ins->insertAfter(NewCI);
633+
return Ins;
634+
}
635+
return NewCI;
636+
};
637+
638+
mutateCallInstOCL(M, CI, ModifyArguments, ModifyRetTy, &Attrs);
639+
}
640+
566641
void SPIRVToOCL::visitCallSPIRVBuiltin(CallInst *CI, Op OC) {
567642
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
568643
mutateCallInstOCL(

lib/SPIRV/SPIRVToOCL.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class SPIRVToOCL : public ModulePass, public InstVisitor<SPIRVToOCL> {
113113
/// => wait_group_events(NumEvents, EventsList)
114114
void visitCallGroupWaitEvents(CallInst *CI, Op OC);
115115

116+
/// Transform __spirv_ImageSampleExplicitLod__{ReturnType} to read_imade
117+
void visitCallSPIRVImageSampleExplicitLodBuiltIn(CallInst *CI, Op OC);
118+
116119
/// Transform __spirv_* builtins to OCL 2.0 builtins.
117120
/// No change with arguments.
118121
void visitCallSPIRVBuiltin(CallInst *CI, Op OC);

lib/SPIRV/SPIRVUtil.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,9 +1241,9 @@ std::string getSPIRVImageTypePostfixes(StringRef SampledType,
12411241
SPIRVAccessQualifierKind Acc) {
12421242
std::string S;
12431243
raw_string_ostream OS(S);
1244-
OS << SampledType << kSPIRVTypeName::PostfixDelim << Desc.Dim
1245-
<< kSPIRVTypeName::PostfixDelim << Desc.Depth
1246-
<< kSPIRVTypeName::PostfixDelim << Desc.Arrayed
1244+
OS << kSPIRVTypeName::PostfixDelim << SampledType
1245+
<< kSPIRVTypeName::PostfixDelim << Desc.Dim << kSPIRVTypeName::PostfixDelim
1246+
<< Desc.Depth << kSPIRVTypeName::PostfixDelim << Desc.Arrayed
12471247
<< kSPIRVTypeName::PostfixDelim << Desc.MS << kSPIRVTypeName::PostfixDelim
12481248
<< Desc.Sampled << kSPIRVTypeName::PostfixDelim << Desc.Format
12491249
<< kSPIRVTypeName::PostfixDelim << Acc;
@@ -1318,8 +1318,6 @@ std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc) {
13181318
std::string BaseTy;
13191319
std::string Postfixes;
13201320
raw_string_ostream OS(Postfixes);
1321-
if (!Acc.empty())
1322-
OS << kSPIRVTypeName::PostfixDelim;
13231321
if (Name.startswith(kSPR2TypeName::ImagePrefix)) {
13241322
std::string ImageTyName = getImageBaseTypeName(Name);
13251323
auto Desc = map<SPIRVTypeImageDescriptor>(ImageTyName);

test/transcoding/SampledImage.cl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
// RUN: spirv-val %t.spv
66
// RUN: llvm-spirv -r %t.spv -o %t.rev.bc
77
// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
8+
// RUN: llvm-spirv -r --spirv-target-env=SPV-IR %t.spv -o %t.rev.bc
9+
// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR
10+
// RUN: llvm-spirv %t.rev.bc -spirv-text -o %t.rev.spt
11+
// RUN: FileCheck < %t.rev.spt %s --check-prefix=CHECK-SPIRV
812

913
constant sampler_t constSampl = CLK_FILTER_LINEAR;
1014

@@ -31,13 +35,21 @@ void sample_kernel(image2d_t input, float2 coords, global float4 *results, sampl
3135
// CHECK-SPIRV: SampledImage [[SampledImageTy]] [[SampledImage1:[0-9]+]] [[InputImage]] [[ConstSampler1]]
3236
// CHECK-SPIRV: ImageSampleExplicitLod {{.*}} [[SampledImage1]]
3337
// CHECK-LLVM: call spir_func <4 x float> @_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f(%opencl.image2d_ro_t addrspace(1)* %input, %opencl.sampler_t addrspace(2)* %0, <2 x float> %coords)
38+
// CHECK-SPV-IR: call spir_func %spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImage14ocl_image2d_ro11ocl_sampler(%opencl.image2d_ro_t addrspace(1)* %input, %opencl.sampler_t addrspace(2)* %0)
39+
// CHECK-SPV-IR: call spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS140__spirv_SampledImage__void_1_0_0_0_0_0_0Dv2_fif(%spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* %TempSampledImage, <2 x float> %coords, i32 2, float 0.000000e+00)
3440

3541
// CHECK-SPIRV: SampledImage [[SampledImageTy]] [[SampledImage2:[0-9]+]] [[InputImage]] [[argSampl]]
3642
// CHECK-SPIRV: ImageSampleExplicitLod {{.*}} [[SampledImage2]]
3743
// CHECK-LLVM: call spir_func <4 x float> @_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f(%opencl.image2d_ro_t addrspace(1)* %input, %opencl.sampler_t addrspace(2)* %argSampl, <2 x float> %coords)
44+
// CHECK-SPV-IR: call spir_func %spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImage14ocl_image2d_ro11ocl_sampler(%opencl.image2d_ro_t addrspace(1)* %input, %opencl.sampler_t addrspace(2)* %argSampl)
45+
// CHECK-SPV-IR: call spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS140__spirv_SampledImage__void_1_0_0_0_0_0_0Dv2_fif(%spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* %TempSampledImage4, <2 x float> %coords, i32 2, float 0.000000e+00)
3846

3947
// CHECK-SPIRV: SampledImage [[SampledImageTy]] [[SampledImage3:[0-9]+]] [[InputImage]] [[ConstSampler2]]
4048
// CHECK-SPIRV: ImageSampleExplicitLod {{.*}} [[SampledImage3]]
4149
// CHECK-LLVM: call spir_func <4 x float> @_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f(%opencl.image2d_ro_t addrspace(1)* %input, %opencl.sampler_t addrspace(2)* %{{[0-9]+}}, <2 x float> %coords)
50+
// CHECK-SPV-IR: call spir_func %spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImage14ocl_image2d_ro11ocl_sampler(%opencl.image2d_ro_t addrspace(1)* %input, %opencl.sampler_t addrspace(2)* %1)
51+
// CHECK-SPV-IR: call spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS140__spirv_SampledImage__void_1_0_0_0_0_0_0Dv2_fif(%spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* %TempSampledImage6, <2 x float> %coords, i32 2, float 0.000000e+00)
4252

4353
// CHECK-LLVM: declare spir_func <4 x float> @_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f(%opencl.image2d_ro_t addrspace(1)*, %opencl.sampler_t addrspace(2)*, <2 x float>)
54+
// CHECK-SPV-IR: declare spir_func %spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImage14ocl_image2d_ro11ocl_sampler(%opencl.image2d_ro_t addrspace(1)*, %opencl.sampler_t addrspace(2)*)
55+
// CHECK-SPV-IR: declare spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS140__spirv_SampledImage__void_1_0_0_0_0_0_0Dv2_fif(%spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)*, <2 x float>, i32, float)

0 commit comments

Comments
 (0)