Skip to content
This repository was archived by the owner on Oct 9, 2019. It is now read-only.

Commit 4496e89

Browse files
bashbaugAlexeySotkin
authored andcommitted
LLVM SPIR-V changes for SPV_INTEL_subgroups
1 parent 97bc44d commit 4496e89

11 files changed

+412
-12
lines changed

lib/SPIRV/OCL20ToSPIRV.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,14 @@ class OCL20ToSPIRV: public ModulePass,
260260
const std::string &DemangledName,
261261
unsigned int Offset);
262262

263+
/// For cl_intel_subgroups block read built-ins:
264+
void visitSubgroupBlockReadINTEL(CallInst *CI, StringRef MangledName,
265+
const std::string &DemangledName);
266+
267+
/// For cl_intel_subgroups block write built-ins:
268+
void visitSubgroupBlockWriteINTEL(CallInst *CI, StringRef MangledName,
269+
const std::string &DemangledName);
270+
263271
void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I){
264272
I.dropAllReferences();
265273
I.eraseFromParent();
@@ -511,6 +519,14 @@ OCL20ToSPIRV::visitCallInst(CallInst& CI) {
511519
OCLImageChannelOrderOffset);
512520
return;
513521
}
522+
if (DemangledName.find(kOCLBuiltinName::SubgroupBlockReadINTELPrefix) == 0) {
523+
visitSubgroupBlockReadINTEL(&CI, MangledName, DemangledName);
524+
return;
525+
}
526+
if (DemangledName.find(kOCLBuiltinName::SubgroupBlockWriteINTELPrefix) == 0) {
527+
visitSubgroupBlockWriteINTEL(&CI, MangledName, DemangledName);
528+
return;
529+
}
514530
visitCallBuiltinSimple(&CI, MangledName, DemangledName);
515531
}
516532

@@ -1453,6 +1469,69 @@ void OCL20ToSPIRV::visitCallGetImageChannel(CallInst *CI, StringRef MangledName,
14531469
},
14541470
&Attrs);
14551471
}
1472+
1473+
// The intel_sub_group_block_read built-ins are overloaded to support both
1474+
// buffers and images, but need to be mapped to distinct SPIR-V instructions.
1475+
// Additionally, for block reads, need to distinguish between scalar block
1476+
// reads and vector block reads.
1477+
void OCL20ToSPIRV::visitSubgroupBlockReadINTEL(CallInst *CI, StringRef MangledName,
1478+
const std::string &DemangledName) {
1479+
OCLBuiltinTransInfo Info;
1480+
if (isOCLImageType(CI->getArgOperand(0)->getType()))
1481+
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupImageBlockReadINTEL);
1482+
else
1483+
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupBlockReadINTEL);
1484+
if (CI->getType()->isVectorTy()) {
1485+
switch(CI->getType()->getVectorNumElements()) {
1486+
case 2: Info.Postfix = "_v2"; break;
1487+
case 4: Info.Postfix = "_v4"; break;
1488+
case 8: Info.Postfix = "_v8"; break;
1489+
default: break;
1490+
}
1491+
}
1492+
if (CI->getType()->getScalarSizeInBits() == 16)
1493+
Info.Postfix += "_us";
1494+
else
1495+
Info.Postfix += "_ui";
1496+
AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
1497+
mutateCallInstSPIRV(M, CI,
1498+
[=](CallInst *, std::vector<Value *> &Args) {
1499+
Info.PostProc(Args);
1500+
return Info.UniqName + Info.Postfix;
1501+
},
1502+
&Attrs);
1503+
}
1504+
1505+
// The intel_sub_group_block_write built-ins are similarly overloaded to support
1506+
// both buffers and images but need to be mapped to distinct SPIR-V instructions.
1507+
// Since the type of data to be written is encoded in the mangled name there is
1508+
// no need to do additional work to distinguish between scalar block writes and
1509+
// vector block writes.
1510+
void OCL20ToSPIRV::visitSubgroupBlockWriteINTEL(CallInst *CI, StringRef MangledName,
1511+
const std::string &DemangledName) {
1512+
OCLBuiltinTransInfo Info;
1513+
if (isOCLImageType(CI->getArgOperand(0)->getType()))
1514+
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupImageBlockWriteINTEL);
1515+
else
1516+
Info.UniqName = getSPIRVFuncName(spv::OpSubgroupBlockWriteINTEL);
1517+
unsigned numArgs = CI->getNumArgOperands();
1518+
if (numArgs && CI->getArgOperand(numArgs - 1)->getType()->isVectorTy()) {
1519+
switch(CI->getArgOperand(numArgs - 1)->getType()->getVectorNumElements()) {
1520+
case 2: Info.Postfix = "_v2"; break;
1521+
case 4: Info.Postfix = "_v4"; break;
1522+
case 8: Info.Postfix = "_v8"; break;
1523+
default: break;
1524+
}
1525+
}
1526+
AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
1527+
mutateCallInstSPIRV(M, CI,
1528+
[=](CallInst *, std::vector<Value *> &Args) {
1529+
Info.PostProc(Args);
1530+
return Info.UniqName + Info.Postfix;
1531+
},
1532+
&Attrs);
1533+
}
1534+
14561535
}
14571536

14581537
INITIALIZE_PASS_BEGIN(OCL20ToSPIRV, "cl20tospv", "Transform OCL 2.0 to SPIR-V",

lib/SPIRV/OCLUtil.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ namespace kOCLBuiltinName {
203203
const static char SubGroupAll[] = "sub_group_all";
204204
const static char SubGroupAny[] = "sub_group_any";
205205
const static char WorkPrefix[] = "work_";
206+
const static char SubgroupBlockReadINTELPrefix[] = "intel_sub_group_block_read";
207+
const static char SubgroupBlockWriteINTELPrefix[] = "intel_sub_group_block_write";
206208
}
207209

208210
/// Offset for OpenCL image channel order enumeration values.
@@ -608,6 +610,11 @@ _SPIRV_OP(get_image_channel_data_type, ImageQueryFormat)
608610
_SPIRV_OP(get_image_channel_order, ImageQueryOrder)
609611
_SPIRV_OP(get_image_num_mip_levels, ImageQueryLevels)
610612
_SPIRV_OP(get_image_num_samples, ImageQuerySamples)
613+
// Intel Subgroups builtins
614+
_SPIRV_OP(intel_sub_group_shuffle, SubgroupShuffleINTEL)
615+
_SPIRV_OP(intel_sub_group_shuffle_down, SubgroupShuffleDownINTEL)
616+
_SPIRV_OP(intel_sub_group_shuffle_up, SubgroupShuffleUpINTEL)
617+
_SPIRV_OP(intel_sub_group_shuffle_xor, SubgroupShuffleXorINTEL)
611618
#undef _SPIRV_OP
612619
}
613620

lib/SPIRV/SPIRVReader.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1968,7 +1968,8 @@ SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
19681968
auto OC = BV->getOpCode();
19691969
if (isSPIRVCmpInstTransToLLVMInst(static_cast<SPIRVInstruction*>(BV))) {
19701970
return mapValue(BV, transCmpInst(BV, BB, F));
1971-
} else if (OCLSPIRVBuiltinMap::rfind(OC, nullptr) &&
1971+
} else if ((OCLSPIRVBuiltinMap::rfind(OC, nullptr) ||
1972+
isIntelSubgroupOpCode(OC)) &&
19721973
!isAtomicOpCode(OC) &&
19731974
!isGroupOpCode(OC) &&
19741975
!isPipeOpCode(OC)) {
@@ -2210,6 +2211,34 @@ SPIRVToLLVM::getOCLBuiltinName(SPIRVInstruction* BI) {
22102211
(EleTy->isTypeArray() && Dim >= 2 && Dim <= 3));
22112212
return std::string(kOCLBuiltinName::NDRangePrefix) + OS.str() + "D";
22122213
}
2214+
if (isIntelSubgroupOpCode(OC)) {
2215+
std::stringstream Name;
2216+
SPIRVType *DataTy = nullptr;
2217+
switch (OC) {
2218+
case OpSubgroupBlockReadINTEL:
2219+
case OpSubgroupImageBlockReadINTEL:
2220+
Name << "intel_sub_group_block_read";
2221+
DataTy = BI->getType();
2222+
break;
2223+
case OpSubgroupBlockWriteINTEL:
2224+
Name << "intel_sub_group_block_write";
2225+
DataTy = BI->getOperands()[1]->getType();
2226+
break;
2227+
case OpSubgroupImageBlockWriteINTEL:
2228+
Name << "intel_sub_group_block_write";
2229+
DataTy = BI->getOperands()[2]->getType();
2230+
break;
2231+
default:
2232+
return OCLSPIRVBuiltinMap::rmap(OC);
2233+
}
2234+
if (DataTy && DataTy->isTypeVector()) {
2235+
if (DataTy->getVectorComponentType()->getBitWidth() == 16)
2236+
Name << "_us";
2237+
if (unsigned ComponentCount = DataTy->getVectorComponentCount())
2238+
Name << ComponentCount;
2239+
}
2240+
return Name.str();
2241+
}
22132242
auto Name = OCLSPIRVBuiltinMap::rmap(OC);
22142243

22152244
SPIRVType *T = nullptr;

lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,7 +1867,7 @@ class SPIRVLifetime : public SPIRVInstruction {
18671867
setHasNoId();
18681868
setHasNoType();
18691869
}
1870-
SPIRVCapVec getRequiredCapability() const {
1870+
SPIRVCapVec getRequiredCapability() const override {
18711871
return getVec(CapabilityKernel);
18721872
}
18731873
SPIRVValue *getObject() { return getValue(Object); };
@@ -1952,7 +1952,7 @@ enum SPIRVOpKind {
19521952

19531953
class SPIRVDevEnqInstBase:public SPIRVInstTemplateBase {
19541954
public:
1955-
SPIRVCapVec getRequiriedCapability() const {
1955+
SPIRVCapVec getRequiredCapability() const override {
19561956
return getVec(CapabilityDeviceEnqueue);
19571957
}
19581958
};
@@ -1979,7 +1979,7 @@ _SPIRV_OP(BuildNDRange, true, 6)
19791979

19801980
class SPIRVPipeInstBase:public SPIRVInstTemplateBase {
19811981
public:
1982-
SPIRVCapVec getRequiriedCapability() const {
1982+
SPIRVCapVec getRequiredCapability() const override {
19831983
return getVec(CapabilityPipes);
19841984
}
19851985
};
@@ -2003,7 +2003,7 @@ _SPIRV_OP(GetMaxPipePackets, true, 6)
20032003

20042004
class SPIRVPipeStorageInstBase :public SPIRVInstTemplateBase {
20052005
public:
2006-
SPIRVCapVec getRequiriedCapability() const {
2006+
SPIRVCapVec getRequiredCapability() const override {
20072007
return getVec(CapabilityPipeStorage, CapabilityPipes);
20082008
}
20092009
};
@@ -2017,7 +2017,7 @@ _SPIRV_OP(CreatePipeFromPipeStorage, true, 4)
20172017

20182018
class SPIRVGroupInstBase:public SPIRVInstTemplateBase {
20192019
public:
2020-
SPIRVCapVec getRequiriedCapability() const {
2020+
SPIRVCapVec getRequiredCapability() const override {
20212021
return getVec(CapabilityGroups);
20222022
}
20232023
};
@@ -2046,7 +2046,7 @@ _SPIRV_OP(GroupCommitWritePipe, false, 6)
20462046

20472047
class SPIRVAtomicInstBase:public SPIRVInstTemplateBase {
20482048
public:
2049-
SPIRVCapVec getRequiriedCapability() const {
2049+
SPIRVCapVec getRequiredCapability() const override {
20502050
return getVec(CapabilityInt64Atomics);
20512051
}
20522052
};
@@ -2078,7 +2078,7 @@ _SPIRV_OP(MemoryBarrier, false, 3)
20782078

20792079
class SPIRVImageInstBase:public SPIRVInstTemplateBase {
20802080
public:
2081-
SPIRVCapVec getRequiriedCapability() const {
2081+
SPIRVCapVec getRequiredCapability() const override {
20822082
return getVec(CapabilityImageBasic);
20832083
}
20842084
};
@@ -2110,6 +2110,54 @@ _SPIRV_OP(GenericPtrMemSemantics, true, 4, false)
21102110
_SPIRV_OP(GenericCastToPtrExplicit, true, 5, false, 1)
21112111
#undef _SPIRV_OP
21122112

2113+
class SPIRVSubgroupShuffleINTELInstBase:public SPIRVInstTemplateBase {
2114+
protected:
2115+
SPIRVCapVec getRequiredCapability() const override {
2116+
return getVec(CapabilitySubgroupShuffleINTEL);
2117+
}
2118+
};
2119+
2120+
#define _SPIRV_OP(x, ...) \
2121+
typedef SPIRVInstTemplate<SPIRVSubgroupShuffleINTELInstBase, Op##x, __VA_ARGS__> \
2122+
SPIRV##x;
2123+
// Intel Subgroup Shuffle Instructions
2124+
_SPIRV_OP(SubgroupShuffleINTEL, true, 5)
2125+
_SPIRV_OP(SubgroupShuffleDownINTEL, true, 6)
2126+
_SPIRV_OP(SubgroupShuffleUpINTEL, true, 6)
2127+
_SPIRV_OP(SubgroupShuffleXorINTEL, true, 5)
2128+
#undef _SPIRV_OP
2129+
2130+
class SPIRVSubgroupBufferBlockIOINTELInstBase:public SPIRVInstTemplateBase {
2131+
protected:
2132+
SPIRVCapVec getRequiredCapability() const override {
2133+
return getVec(CapabilitySubgroupBufferBlockIOINTEL);
2134+
}
2135+
};
2136+
2137+
#define _SPIRV_OP(x, ...) \
2138+
typedef SPIRVInstTemplate<SPIRVSubgroupBufferBlockIOINTELInstBase, Op##x, __VA_ARGS__> \
2139+
SPIRV##x;
2140+
// Intel Subgroup Buffer Block Read and Write Instructions
2141+
_SPIRV_OP(SubgroupBlockReadINTEL, true, 4)
2142+
_SPIRV_OP(SubgroupBlockWriteINTEL, false, 3)
2143+
#undef _SPIRV_OP
2144+
2145+
class SPIRVSubgroupImageBlockIOINTELInstBase:public SPIRVInstTemplateBase {
2146+
protected:
2147+
SPIRVCapVec getRequiredCapability() const override {
2148+
return getVec(CapabilitySubgroupImageBlockIOINTEL);
2149+
}
2150+
};
2151+
2152+
#define _SPIRV_OP(x, ...) \
2153+
typedef SPIRVInstTemplate<SPIRVSubgroupImageBlockIOINTELInstBase, Op##x, __VA_ARGS__> \
2154+
SPIRV##x;
2155+
// Intel Subgroup Image Block Read and Write Instructions
2156+
_SPIRV_OP(SubgroupImageBlockReadINTEL, true, 5)
2157+
_SPIRV_OP(SubgroupImageBlockWriteINTEL, false, 4)
2158+
#undef _SPIRV_OP
2159+
2160+
21132161
SPIRVSpecConstantOp *createSpecConstantOpInst(SPIRVInstruction *Inst);
21142162
SPIRVInstruction *createInstFromSpecConstantOp(SPIRVSpecConstantOp *C);
21152163
}

lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,14 @@ isValid(spv::Op V) {
884884
case OpMemoryNamedBarrier:
885885
case OpModuleProcessed:
886886
case OpForward:
887+
case OpSubgroupShuffleINTEL:
888+
case OpSubgroupShuffleDownINTEL:
889+
case OpSubgroupShuffleUpINTEL:
890+
case OpSubgroupShuffleXorINTEL:
891+
case OpSubgroupBlockReadINTEL:
892+
case OpSubgroupBlockWriteINTEL:
893+
case OpSubgroupImageBlockReadINTEL:
894+
case OpSubgroupImageBlockWriteINTEL:
887895
return true;
888896
default:
889897
return false;

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,9 @@ SPIRVMap<Capability, std::string>::init() {
478478
add(CapabilityStorageImageReadWithoutFormat, "StorageImageReadWithoutFormat");
479479
add(CapabilityStorageImageWriteWithoutFormat, "StorageImageWriteWithoutFormat");
480480
add(CapabilityMultiViewport, "MultiViewport");
481+
add(CapabilitySubgroupShuffleINTEL, "SubgroupShuffleINTEL");
482+
add(CapabilitySubgroupBufferBlockIOINTEL, "SubgroupBufferBlockIOINTEL");
483+
add(CapabilitySubgroupImageBlockIOINTEL, "SubgroupImageBlockIOINTEL");
481484
}
482485
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
483486

lib/SPIRV/libSPIRV/SPIRVOpCode.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ inline bool isModuleScopeAllowedOpCode(Op OpCode) {
169169
isConstantOpCode(OpCode);
170170
}
171171

172+
inline bool isIntelSubgroupOpCode(Op OpCode) {
173+
unsigned OC = OpCode;
174+
return OpSubgroupShuffleINTEL <= OC && OC <=OpSubgroupImageBlockWriteINTEL;
175+
}
172176
}
173177

174178
#endif /* SPIRVOPCODE_HPP_ */

lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,11 @@ _SPIRV_OP(TypePipeStorage, 322)
295295
_SPIRV_OP(ConstantPipeStorage, 323)
296296
_SPIRV_OP(CreatePipeFromPipeStorage, 324)
297297
_SPIRV_OP(Forward, 1024)
298+
_SPIRV_OP(SubgroupShuffleINTEL, 5571)
299+
_SPIRV_OP(SubgroupShuffleDownINTEL, 5572)
300+
_SPIRV_OP(SubgroupShuffleUpINTEL, 5573)
301+
_SPIRV_OP(SubgroupShuffleXorINTEL, 5574)
302+
_SPIRV_OP(SubgroupBlockReadINTEL, 5575)
303+
_SPIRV_OP(SubgroupBlockWriteINTEL, 5576)
304+
_SPIRV_OP(SubgroupImageBlockReadINTEL, 5577)
305+
_SPIRV_OP(SubgroupImageBlockWriteINTEL, 5578)

lib/SPIRV/libSPIRV/SPIRVType.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ class SPIRVTypeVector:public SPIRVType {
281281
bool isValidIndex(SPIRVWord Index) const { return Index < CompCount;}
282282
SPIRVCapVec getRequiredCapability() const {
283283
SPIRVCapVec V(getComponentType()->getRequiredCapability());
284-
if (CompCount >= 8)
284+
if (CompCount > 8)
285285
V.push_back(CapabilityVector16);
286286
return std::move(V);
287287
}

0 commit comments

Comments
 (0)