Skip to content

Commit

Permalink
Add support for SPV_INTEL_usm_storage_classes extension
Browse files Browse the repository at this point in the history
With this extension 2 new Storage Classes are introduced:
DeviceOnlyINTEL and HostOnlyINTEL appropriately mapped on
global_device and global_host SYCL/OpenCL address spaces which
are part of SYCL_INTEL_usm_address_spaces extension.

In case if device doesn't support SPV_INTEL_usm_storage_classes
extension global_device and global_host address spaces are lowered
to just global address space and therefore new Storage Classes are
lowered to CrossWorkgroup storage class.

Also this patch introduces a flag 'enable-usm-addrspaces' that
enables generation of global_device and global_host address spaces
during reversed translation.

Spec: intel/llvm#1840

Co-authored-by: Viktoria Maksimova <[email protected]>

Signed-off-by: Dmitry Sidorov <[email protected]>
Signed-off-by: Viktoria Maksimova <[email protected]>
  • Loading branch information
MrSidims committed Jun 9, 2020
1 parent eeca450 commit a5bfb9d
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 13 deletions.
1 change: 1 addition & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ EXT(SPV_INTEL_io_pipes)
EXT(SPV_INTEL_inline_assembly)
EXT(SPV_INTEL_arbitrary_precision_integers)
EXT(SPV_INTEL_optimization_hints)
EXT(SPV_INTEL_usm_storage_classes)
11 changes: 11 additions & 0 deletions include/LLVMSPIRVOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ class TranslatorOpts {

FPContractMode getFPContractMode() const { return FPCMode; }

void enableUsmAddrspaces() { EnableUsmAddrspaces = true; }

bool isUsmAddrspacesEnabled() { return EnableUsmAddrspaces; }

private:
// Common translation options
VersionNumber MaxVersion = VersionNumber::MaximumVersion;
Expand All @@ -159,6 +163,13 @@ class TranslatorOpts {
// - FPContractMode::Fast allows *all* operations to be contracted
// for all entry points
FPContractMode FPCMode = FPContractMode::On;
// Controls translation of USM storage classes to USM address spaces.
//
// - true allows to use USM storage/addrspace
//
// - false prohibit translation of USM storage classess to USM addrspaces.
// Instead, USM storage is translated to common global addrspace.
bool EnableUsmAddrspaces = false;
};

} // namespace SPIRV
Expand Down
4 changes: 3 additions & 1 deletion lib/SPIRV/Mangler/ParameterType.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ enum TypeAttributeEnum {
ATTR_CONSTANT,
ATTR_LOCAL,
ATTR_GENERIC,
ATTR_ADDR_SPACE_LAST = ATTR_GENERIC,
ATTR_GLOBAL_DEVICE,
ATTR_GLOBAL_HOST,
ATTR_ADDR_SPACE_LAST = ATTR_GLOBAL_HOST,
ATTR_NONE,
ATTR_NUM = ATTR_NONE
};
Expand Down
4 changes: 4 additions & 0 deletions lib/SPIRV/OCLUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ static SPIR::TypeAttributeEnum mapAddrSpaceEnums(SPIRAddressSpace Addrspace) {
return SPIR::ATTR_LOCAL;
case SPIRAS_Generic:
return SPIR::ATTR_GENERIC;
case SPIRAS_GlobalDevice:
return SPIR::ATTR_GLOBAL_DEVICE;
case SPIRAS_GlobalHost:
return SPIR::ATTR_GLOBAL_HOST;
default:
llvm_unreachable("Invalid addrspace enum member");
}
Expand Down
6 changes: 6 additions & 0 deletions lib/SPIRV/SPIRVInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ enum SPIRAddressSpace {
SPIRAS_Input,
SPIRAS_Output,
SPIRAS_Count,
SPIRAS_GlobalDevice = 11,
SPIRAS_GlobalHost = 12,
};

template <> inline void SPIRVMap<SPIRAddressSpace, std::string>::init() {
Expand All @@ -200,6 +202,8 @@ template <> inline void SPIRVMap<SPIRAddressSpace, std::string>::init() {
add(SPIRAS_Local, "Local");
add(SPIRAS_Generic, "Generic");
add(SPIRAS_Input, "Input");
add(SPIRAS_GlobalDevice, "GlobalDevice");
add(SPIRAS_GlobalHost, "GlobalHost");
}
typedef SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind>
SPIRAddrSpaceCapitalizedNameMap;
Expand All @@ -212,6 +216,8 @@ inline void SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind>::init() {
add(SPIRAS_Local, StorageClassWorkgroup);
add(SPIRAS_Generic, StorageClassGeneric);
add(SPIRAS_Input, StorageClassInput);
add(SPIRAS_GlobalDevice, StorageClassDeviceOnlyINTEL);
add(SPIRAS_GlobalHost, StorageClassHostOnlyINTEL);
}
typedef SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind> SPIRSPIRVAddrSpaceMap;

Expand Down
35 changes: 28 additions & 7 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,11 +382,18 @@ Type *SPIRVToLLVM::transType(SPIRVType *T, bool IsClassMember) {
case OpTypeArray:
return mapType(T, ArrayType::get(transType(T->getArrayElementType()),
T->getArrayLength()));
case OpTypePointer:
case OpTypePointer: {
SPIRAddressSpace AS =
SPIRSPIRVAddrSpaceMap::rmap(T->getPointerStorageClass());
// If generation of SYCL USM address spaces isn't allowed in the reversed
// translation - transform them into global address space
if (!BM->isUsmAddrspacesEnabled() && (AS == SPIRAS_GlobalDevice ||
AS == SPIRAS_GlobalHost))
AS = SPIRAS_Global;
return mapType(
T, PointerType::get(
transType(T->getPointerElementType(), IsClassMember),
SPIRSPIRVAddrSpaceMap::rmap(T->getPointerStorageClass())));
transType(T->getPointerElementType(), IsClassMember), AS));
}
case OpTypeVector:
return mapType(T, VectorType::get(transType(T->getVectorComponentType()),
T->getVectorComponentCount()));
Expand Down Expand Up @@ -928,9 +935,18 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F,
Dst->getScalarSizeInBits() > Src->getType()->getScalarSizeInBits();
switch (BC->getOpCode()) {
case OpPtrCastToGeneric:
case OpGenericCastToPtr:
case OpGenericCastToPtr: {
// If module has pointers with DeviceOnlyINTEL and HostOnlyINTEL storage
// classes and if during reversed translation 'enable-usm-addrspaces'
// wasn't passed there will be a situation, when global_device/global_host
// address space will be lowered to just global address space. If there also
// is an addrspacecast - we need to replace it with source pointer.
if (Src->getType()->getPointerAddressSpace() ==
Dst->getPointerAddressSpace())
return Src;
CO = Instruction::AddrSpaceCast;
break;
}
case OpSConvert:
CO = IsExt ? Instruction::SExt : Instruction::Trunc;
break;
Expand Down Expand Up @@ -3358,15 +3374,20 @@ bool SPIRVToLLVM::transOCLMetadata(SPIRVFunction *BF) {
if (F->getCallingConv() != CallingConv::SPIR_KERNEL)
return true;

// Generate metadata for kernel_arg_address_spaces
// Generate metadata for kernel_arg_addr_space
addOCLKernelArgumentMetadata(
Context, SPIR_MD_KERNEL_ARG_ADDR_SPACE, BF, F,
[=](SPIRVFunctionParameter *Arg) {
SPIRVType *ArgTy = Arg->getType();
SPIRAddressSpace AS = SPIRAS_Private;
if (ArgTy->isTypePointer())
if (ArgTy->isTypePointer()) {
AS = SPIRSPIRVAddrSpaceMap::rmap(ArgTy->getPointerStorageClass());
else if (ArgTy->isTypeOCLImage() || ArgTy->isTypePipe())
// If generation of SYCL USM address spaces isn't allowed in the reversed
// translation - transform them into global address space
if (!BM->isUsmAddrspacesEnabled() && (AS == SPIRAS_GlobalDevice ||
AS == SPIRAS_GlobalHost))
AS = SPIRAS_Global;
} else if (ArgTy->isTypeOCLImage() || ArgTy->isTypePipe())
AS = SPIRAS_Global;
return ConstantAsMetadata::get(
ConstantInt::get(Type::getInt32Ty(*Context), AS));
Expand Down
46 changes: 41 additions & 5 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ SPIRVType *LLVMToSPIRV::transType(Type *T) {
return nullptr;
auto ST = dyn_cast<StructType>(ET);
auto AddrSpc = T->getPointerAddressSpace();
// Lower global_device and global_host address spaces that were added in
// SYCL as part of SYCL_INTEL_usm_address_spaces extension to just global
// address space if device doesn't support SPV_INTEL_usm_storage_classes
// extension
if (!BM->isAllowedToUseExtension(
ExtensionID::SPV_INTEL_usm_storage_classes) &&
((AddrSpc == SPIRAS_GlobalDevice) || (AddrSpc == SPIRAS_GlobalHost)))
AddrSpc = SPIRAS_Global;
if (ST && !ST->isSized()) {
Op OpCode;
StringRef STName = ST->getName();
Expand Down Expand Up @@ -722,14 +730,33 @@ SPIRV::SPIRVInstruction *LLVMToSPIRV::transUnaryInst(UnaryInstruction *U,
Op BOC = OpNop;
SPIRVValue *Op = nullptr;
if (auto Cast = dyn_cast<AddrSpaceCastInst>(U)) {
if (Cast->getDestTy()->getPointerAddressSpace() == SPIRAS_Generic) {
assert(Cast->getSrcTy()->getPointerAddressSpace() != SPIRAS_Constant &&
const auto SrcAddrSpace = Cast->getSrcTy()->getPointerAddressSpace();
const auto DestAddrSpace = Cast->getDestTy()->getPointerAddressSpace();
if (DestAddrSpace == SPIRAS_Generic) {
assert(SrcAddrSpace != SPIRAS_Constant &&
"Casts from constant address space to generic are illegal");
BOC = OpPtrCastToGeneric;
// In SPIR-V only casts to/from generic are allowed. But with
// SPV_INTEL_usm_storage_classes we can also have casts from global_device
// and global_host to global addr space and vice versa.
} else if (SrcAddrSpace == SPIRAS_GlobalDevice ||
SrcAddrSpace == SPIRAS_GlobalHost) {
assert(
(DestAddrSpace == SPIRAS_Global || DestAddrSpace == SPIRAS_Generic) &&
"Casts from global_device/global_host only allowed to \
global/generic");
BOC = OpPtrCastToGeneric;
} else if (DestAddrSpace == SPIRAS_GlobalDevice ||
DestAddrSpace == SPIRAS_GlobalHost) {
assert(
(SrcAddrSpace == SPIRAS_Global || SrcAddrSpace == SPIRAS_Generic) &&
"Casts to global_device/global_host only allowed from \
global/generic");
BOC = OpGenericCastToPtr;
} else {
assert(Cast->getDestTy()->getPointerAddressSpace() != SPIRAS_Constant &&
assert(DestAddrSpace != SPIRAS_Constant &&
"Casts from generic address space to constant are illegal");
assert(Cast->getSrcTy()->getPointerAddressSpace() == SPIRAS_Generic);
assert(SrcAddrSpace == SPIRAS_Generic);
BOC = OpGenericCastToPtr;
}
} else {
Expand Down Expand Up @@ -996,11 +1023,20 @@ SPIRVValue *LLVMToSPIRV::transValueWithoutDecoration(Value *V,
BVarInit = transValue(Init, nullptr);
}

// Lower global_device and global_host address spaces that were added in
// SYCL as part of SYCL_INTEL_usm_address_spaces extension to just global
// address space if device doesn't support SPV_INTEL_usm_storage_classes
// extension
auto AddrSpc = Ty->getAddressSpace();
if (!BM->isAllowedToUseExtension(
ExtensionID::SPV_INTEL_usm_storage_classes) &&
((AddrSpc == SPIRAS_GlobalDevice) || (AddrSpc == SPIRAS_GlobalHost)))
AddrSpc = SPIRAS_Global;
auto BVar = static_cast<SPIRVVariable *>(BM->addVariable(
transType(Ty), GV->isConstant(), transLinkageType(GV), BVarInit,
GV->getName().str(),
SPIRSPIRVAddrSpaceMap::map(
static_cast<SPIRAddressSpace>(Ty->getAddressSpace())),
static_cast<SPIRAddressSpace>(AddrSpc)),
nullptr));
mapValue(V, BVar);
spv::BuiltIn Builtin = spv::BuiltInPosition;
Expand Down
2 changes: 2 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ template <> inline void SPIRVMap<SPIRVStorageClassKind, SPIRVCapVec>::init() {
ADD_VEC_INIT(StorageClassGeneric, {CapabilityGenericPointer});
ADD_VEC_INIT(StorageClassPushConstant, {CapabilityShader});
ADD_VEC_INIT(StorageClassAtomicCounter, {CapabilityAtomicStorage});
ADD_VEC_INIT(StorageClassDeviceOnlyINTEL, {CapabilityUSMStorageClassesINTEL});
ADD_VEC_INIT(StorageClassHostOnlyINTEL, {CapabilityUSMStorageClassesINTEL});
}

template <> inline void SPIRVMap<SPIRVImageDimKind, SPIRVCapVec>::init() {
Expand Down
2 changes: 2 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ inline bool isValid(spv::StorageClass V) {
case StorageClassPushConstant:
case StorageClassAtomicCounter:
case StorageClassImage:
case StorageClassDeviceOnlyINTEL:
case StorageClassHostOnlyINTEL:
return true;
default:
return false;
Expand Down
4 changes: 4 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,10 @@ class SPIRVModule {
return TranslationOpts.getFPContractMode();
}

bool isUsmAddrspacesEnabled() {
return TranslationOpts.isUsmAddrspacesEnabled();
}

// I/O functions
friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M);
friend std::istream &operator>>(std::istream &I, SPIRVModule &M);
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ template <> inline void SPIRVMap<StorageClass, std::string>::init() {
add(StorageClassPushConstant, "PushConstant");
add(StorageClassAtomicCounter, "AtomicCounter");
add(StorageClassImage, "Image");
add(StorageClassDeviceOnlyINTEL, "DeviceOnlyINTEL");
add(StorageClassHostOnlyINTEL, "HostOnlyINTEL");
}
SPIRV_DEF_NAMEMAP(StorageClass, SPIRVStorageClassNameMap)

Expand Down Expand Up @@ -535,6 +537,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
add(CapabilityGroupNonUniformShuffleRelative,
"GroupNonUniformShuffleRelative");
add(CapabilityGroupNonUniformClustered, "GroupNonUniformClustered");
add(CapabilityUSMStorageClassesINTEL, "USMStorageClassesINTEL");
}
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)

Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/libSPIRV/spirv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ enum StorageClass {
StorageClassShaderRecordBufferNV = 5343,
StorageClassPhysicalStorageBuffer = 5349,
StorageClassPhysicalStorageBufferEXT = 5349,
StorageClassDeviceOnlyINTEL = 5936,
StorageClassHostOnlyINTEL = 5937,
StorageClassMax = 0x7fffffff,
};

Expand Down Expand Up @@ -939,6 +941,7 @@ enum Capability {
CapabilityFPGARegINTEL = 5948,
CapabilityKernelAttributesINTEL = 5892,
CapabilityFPGAKernelAttributesINTEL = 5897,
CapabilityUSMStorageClassesINTEL = 5935,
CapabilityIOPipeINTEL = 5943,
CapabilityMax = 0x7fffffff,
};
Expand Down
Loading

0 comments on commit a5bfb9d

Please sign in to comment.