Skip to content

Commit 4fdcbaa

Browse files
aus-intelvladimirlaz
authored andcommitted
Add support for read/write ocl builtins from cl_intel_subgroups_{char|long}
Link to PR with extension: KhronosGroup/OpenCL-Registry#79.
1 parent 8d287a0 commit 4fdcbaa

File tree

5 files changed

+230
-130
lines changed

5 files changed

+230
-130
lines changed

llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,29 @@ void OCL20ToSPIRV::visitCallKernelQuery(CallInst *CI, StringRef DemangledName) {
15971597
/*BuiltinFuncMangleInfo*/ nullptr, &Attrs);
15981598
}
15991599

1600+
// Add postfix to overloaded intel subgroup block read/write builtins
1601+
// so new functions can be distinguished.
1602+
static void processSubgroupBlockReadWriteINTEL(CallInst *CI,
1603+
OCLBuiltinTransInfo &Info,
1604+
const Type *DataTy, Module *M) {
1605+
unsigned VectorNumElements = 1;
1606+
if (DataTy->isVectorTy())
1607+
VectorNumElements = DataTy->getVectorNumElements();
1608+
unsigned ElementBitSize = DataTy->getScalarSizeInBits();
1609+
Info.Postfix = "_";
1610+
Info.Postfix +=
1611+
getIntelSubgroupBlockDataPostfix(ElementBitSize, VectorNumElements);
1612+
assert(CI->getCalledFunction() && "Unexpected indirect call");
1613+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
1614+
mutateCallInstSPIRV(
1615+
M, CI,
1616+
[&Info](CallInst *, std::vector<Value *> &Args) {
1617+
Info.PostProc(Args);
1618+
return Info.UniqName + Info.Postfix;
1619+
},
1620+
&Attrs);
1621+
}
1622+
16001623
// The intel_sub_group_block_read built-ins are overloaded to support both
16011624
// buffers and images, but need to be mapped to distinct SPIR-V instructions.
16021625
// Additionally, for block reads, need to distinguish between scalar block
@@ -1607,70 +1630,24 @@ void OCL20ToSPIRV::visitSubgroupBlockReadINTEL(CallInst *CI) {
16071630
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupImageBlockReadINTEL);
16081631
else
16091632
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupBlockReadINTEL);
1610-
if (CI->getType()->isVectorTy()) {
1611-
switch (cast<VectorType>(CI->getType())->getNumElements()) {
1612-
case 2:
1613-
Info.Postfix = "_v2";
1614-
break;
1615-
case 4:
1616-
Info.Postfix = "_v4";
1617-
break;
1618-
case 8:
1619-
Info.Postfix = "_v8";
1620-
break;
1621-
default:
1622-
break;
1623-
}
1624-
}
1625-
if (CI->getType()->getScalarSizeInBits() == 16)
1626-
Info.Postfix += "_us";
1627-
else
1628-
Info.Postfix += "_ui";
1629-
assert(CI->getCalledFunction() && "Unexpected indirect call");
1630-
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
1631-
mutateCallInstSPIRV(M, CI,
1632-
[=](CallInst *, std::vector<Value *> &Args) {
1633-
Info.PostProc(Args);
1634-
return Info.UniqName + Info.Postfix;
1635-
},
1636-
&Attrs);
1633+
Type *DataTy = CI->getType();
1634+
processSubgroupBlockReadWriteINTEL(CI, Info, DataTy, M);
16371635
}
16381636

16391637
// The intel_sub_group_block_write built-ins are similarly overloaded to support
16401638
// both buffers and images but need to be mapped to distinct SPIR-V
1641-
// instructions. Since the type of data to be written is encoded in the mangled
1642-
// name there is no need to do additional work to distinguish between scalar
1643-
// block writes and vector block writes.
1639+
// instructions.
16441640
void OCL20ToSPIRV::visitSubgroupBlockWriteINTEL(CallInst *CI) {
16451641
OCLBuiltinTransInfo Info;
16461642
if (isOCLImageType(CI->getArgOperand(0)->getType()))
16471643
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupImageBlockWriteINTEL);
16481644
else
16491645
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupBlockWriteINTEL);
1650-
unsigned NumArgs = CI->getNumArgOperands();
1651-
if (NumArgs && CI->getArgOperand(NumArgs - 1)->getType()->isVectorTy()) {
1652-
switch (cast<VectorType>(CI->getArgOperand(NumArgs - 1)->getType())->getNumElements()) {
1653-
case 2:
1654-
Info.Postfix = "_v2";
1655-
break;
1656-
case 4:
1657-
Info.Postfix = "_v4";
1658-
break;
1659-
case 8:
1660-
Info.Postfix = "_v8";
1661-
break;
1662-
default:
1663-
break;
1664-
}
1665-
}
1666-
assert(CI->getCalledFunction() && "Unexpected indirect call");
1667-
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
1668-
mutateCallInstSPIRV(M, CI,
1669-
[=](CallInst *, std::vector<Value *> &Args) {
1670-
Info.PostProc(Args);
1671-
return Info.UniqName + Info.Postfix;
1672-
},
1673-
&Attrs);
1646+
assert(!CI->arg_empty() &&
1647+
"Intel subgroup block write should have arguments");
1648+
unsigned DataArg = CI->getNumArgOperands() - 1;
1649+
Type *DataTy = CI->getArgOperand(DataArg)->getType();
1650+
processSubgroupBlockReadWriteINTEL(CI, Info, DataTy, M);
16741651
}
16751652

16761653
void OCL20ToSPIRV::visitSubgroupImageMediaBlockINTEL(CallInst *CI,

llvm-spirv/lib/SPIRV/OCLUtil.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,46 @@ void checkFpContract(BinaryOperator *B, SPIRVBasicBlock *BB) {
903903
}
904904
}
905905
}
906+
907+
std::string getIntelSubgroupBlockDataPostfix(unsigned ElementBitSize,
908+
unsigned VectorNumElements) {
909+
std::ostringstream OSS;
910+
switch (ElementBitSize) {
911+
case 8:
912+
OSS << "_uc";
913+
break;
914+
case 16:
915+
OSS << "_us";
916+
break;
917+
case 32:
918+
// Intentionally does nothing since _ui variant is only an alias.
919+
break;
920+
case 64:
921+
OSS << "_ul";
922+
break;
923+
default:
924+
llvm_unreachable(
925+
"Incorrect data bitsize for intel_subgroup_block builtins");
926+
}
927+
switch (VectorNumElements) {
928+
case 1:
929+
break;
930+
case 2:
931+
case 4:
932+
case 8:
933+
OSS << VectorNumElements;
934+
break;
935+
case 16:
936+
assert(ElementBitSize == 8 &&
937+
"16 elements vector allowed only for char builtins");
938+
OSS << VectorNumElements;
939+
break;
940+
default:
941+
llvm_unreachable(
942+
"Incorrect vector length for intel_subgroup_block builtins");
943+
}
944+
return OSS.str();
945+
}
906946
} // namespace OCLUtil
907947

908948
void llvm::mangleOpenClBuiltin(const std::string &UniqName,

llvm-spirv/lib/SPIRV/OCLUtil.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,12 @@ template <typename T> std::string toString(const T *Object) {
437437
RSOS.flush();
438438
return S;
439439
}
440+
441+
// Get data and vector size postfix for sugroup_block_{read|write} builtins
442+
// as specified by cl_intel_subgroups* extensions.
443+
// Scalar data assumed to be represented as vector of one element.
444+
std::string getIntelSubgroupBlockDataPostfix(unsigned ElementBitSize,
445+
unsigned VectorNumElements);
440446
} // namespace OCLUtil
441447

442448
///////////////////////////////////////////////////////////////////////////////

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,14 +2818,12 @@ std::string SPIRVToLLVM::getOCLBuiltinName(SPIRVInstruction *BI) {
28182818
default:
28192819
return OCLSPIRVBuiltinMap::rmap(OC);
28202820
}
2821-
if (DataTy) {
2822-
if (DataTy->getBitWidth() == 16)
2823-
Name << "_us";
2824-
if (DataTy->isTypeVector()) {
2825-
if (unsigned ComponentCount = DataTy->getVectorComponentCount())
2826-
Name << ComponentCount;
2827-
}
2828-
}
2821+
assert(DataTy && "Intel subgroup block builtins should have data type");
2822+
unsigned VectorNumElements = 1;
2823+
if (DataTy->isTypeVector())
2824+
VectorNumElements = DataTy->getVectorComponentCount();
2825+
unsigned ElementBitSize = DataTy->getBitWidth();
2826+
Name << getIntelSubgroupBlockDataPostfix(ElementBitSize, VectorNumElements);
28292827
return Name.str();
28302828
}
28312829
if (isSubgroupAvcINTELInstructionOpCode(OC))

0 commit comments

Comments
 (0)