diff --git a/llvm-spirv/include/LLVMSPIRVExtensions.inc b/llvm-spirv/include/LLVMSPIRVExtensions.inc index a3660d4452a3c..ecf31f72cc190 100644 --- a/llvm-spirv/include/LLVMSPIRVExtensions.inc +++ b/llvm-spirv/include/LLVMSPIRVExtensions.inc @@ -21,3 +21,4 @@ EXT(SPV_INTEL_arbitrary_precision_integers) EXT(SPV_INTEL_optimization_hints) EXT(SPV_INTEL_float_controls2) EXT(SPV_INTEL_vector_compute) +EXT(SPV_INTEL_usm_storage_classes) diff --git a/llvm-spirv/lib/SPIRV/Mangler/ParameterType.h b/llvm-spirv/lib/SPIRV/Mangler/ParameterType.h index a9ec51d48ae0c..cd05954194ed8 100644 --- a/llvm-spirv/lib/SPIRV/Mangler/ParameterType.h +++ b/llvm-spirv/lib/SPIRV/Mangler/ParameterType.h @@ -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 }; diff --git a/llvm-spirv/lib/SPIRV/OCLUtil.cpp b/llvm-spirv/lib/SPIRV/OCLUtil.cpp index 747913795c56b..c05955b5d913f 100644 --- a/llvm-spirv/lib/SPIRV/OCLUtil.cpp +++ b/llvm-spirv/lib/SPIRV/OCLUtil.cpp @@ -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"); } diff --git a/llvm-spirv/lib/SPIRV/SPIRVInternal.h b/llvm-spirv/lib/SPIRV/SPIRVInternal.h index 2705fa4524a68..c0d285684d3a5 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVInternal.h +++ b/llvm-spirv/lib/SPIRV/SPIRVInternal.h @@ -188,6 +188,8 @@ enum SPIRAddressSpace { SPIRAS_Constant, SPIRAS_Local, SPIRAS_Generic, + SPIRAS_GlobalDevice, + SPIRAS_GlobalHost, SPIRAS_Input, SPIRAS_Output, SPIRAS_Count, @@ -200,6 +202,8 @@ template <> inline void SPIRVMap::init() { add(SPIRAS_Local, "Local"); add(SPIRAS_Generic, "Generic"); add(SPIRAS_Input, "Input"); + add(SPIRAS_GlobalDevice, "GlobalDevice"); + add(SPIRAS_GlobalHost, "GlobalHost"); } typedef SPIRVMap SPIRAddrSpaceCapitalizedNameMap; @@ -212,6 +216,8 @@ inline void SPIRVMap::init() { add(SPIRAS_Local, StorageClassWorkgroup); add(SPIRAS_Generic, StorageClassGeneric); add(SPIRAS_Input, StorageClassInput); + add(SPIRAS_GlobalDevice, StorageClassDeviceOnlyINTEL); + add(SPIRAS_GlobalHost, StorageClassHostOnlyINTEL); } typedef SPIRVMap SPIRSPIRVAddrSpaceMap; diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp index 4afca8dfa52f1..e0ba664d3ee55 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp @@ -931,8 +931,18 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F, switch (BC->getOpCode()) { case OpPtrCastToGeneric: case OpGenericCastToPtr: + case OpPtrCastToCrossWorkgroupINTEL: + case OpCrossWorkgroupCastToPtrINTEL: { + // If module has pointers with DeviceOnlyINTEL and HostOnlyINTEL storage + // classes 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; @@ -3359,7 +3369,7 @@ 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) { diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index af79bce6da471..e7259fed7399e 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -307,6 +307,14 @@ SPIRVType *LLVMToSPIRV::transType(Type *T) { return nullptr; auto ST = dyn_cast(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(); @@ -760,14 +768,47 @@ SPIRV::SPIRVInstruction *LLVMToSPIRV::transUnaryInst(UnaryInstruction *U, Op BOC = OpNop; SPIRVValue *Op = nullptr; if (auto Cast = dyn_cast(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"); + if (!BM->isAllowedToUseExtension( + ExtensionID::SPV_INTEL_usm_storage_classes)) { + if (DestAddrSpace == SPIRAS_Global) + return nullptr; + BOC = OpPtrCastToGeneric; + } else { + BOC = OpPtrCastToCrossWorkgroupINTEL; + } + } 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"); + if (!BM->isAllowedToUseExtension( + ExtensionID::SPV_INTEL_usm_storage_classes)) { + if (SrcAddrSpace == SPIRAS_Global) + return nullptr; + BOC = OpGenericCastToPtr; + } else { + BOC = OpCrossWorkgroupCastToPtrINTEL; + } } 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 { @@ -1056,8 +1097,18 @@ SPIRVValue *LLVMToSPIRV::transValueWithoutDecoration(Value *V, if (IsVectorCompute) StorageClass = VectorComputeUtil::getVCGlobalVarStorageClass(AddressSpace); - else + else { + // 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 ((AddressSpace == SPIRAS_GlobalDevice || + AddressSpace == SPIRAS_GlobalHost) && + !BM->isAllowedToUseExtension( + ExtensionID::SPV_INTEL_usm_storage_classes)) + AddressSpace = SPIRAS_Global; StorageClass = SPIRSPIRVAddrSpaceMap::map(AddressSpace); + } auto BVar = static_cast( BM->addVariable(transType(Ty), GV->isConstant(), transLinkageType(GV), @@ -1315,7 +1366,8 @@ SPIRVValue *LLVMToSPIRV::transValueWithoutDecoration(Value *V, if (UnaryInstruction *U = dyn_cast(V)) { if (isSpecialTypeInitializer(U)) return mapValue(V, transValue(U->getOperand(0), BB)); - return mapValue(V, transUnaryInst(U, BB)); + auto UI = transUnaryInst(U, BB); + return mapValue(V, UI ? UI : transValue(U->getOperand(0), BB)); } if (GetElementPtrInst *GEP = dyn_cast(V)) { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h index d374ee8e6b57b..09bcc12c13f8f 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h @@ -266,6 +266,8 @@ template <> inline void SPIRVMap::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::init() { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp index ff97b3b9be540..50272d0cd7c27 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp @@ -183,6 +183,8 @@ bool isSpecConstantOpAllowedOp(Op OC) { OpConvertUToPtr, OpGenericCastToPtr, OpPtrCastToGeneric, + OpCrossWorkgroupCastToPtrINTEL, + OpPtrCastToCrossWorkgroupINTEL, OpBitcast, OpQuantizeToF16, OpSNegate, diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h index c20ad86fd3c9f..4ea503613854f 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h @@ -538,9 +538,15 @@ class SPIRVStore : public SPIRVInstruction, public SPIRVMemoryAccess { SPIRVInstruction::validate(); if (getSrc()->isForward() || getDst()->isForward()) return; - assert(getValueType(PtrId)->getPointerElementType() == - getValueType(ValId) && - "Inconsistent operand types"); +#ifndef NDEBUG + if (getValueType(PtrId)->getPointerElementType() != getValueType(ValId)) { + assert(getValueType(PtrId) + ->getPointerElementType() + ->getPointerStorageClass() == + getValueType(ValId)->getPointerStorageClass() && + "Inconsistent operand types"); + } +#endif // NDEBUG } private: @@ -1603,6 +1609,8 @@ _SPIRV_OP(ConvertPtrToU) _SPIRV_OP(ConvertUToPtr) _SPIRV_OP(PtrCastToGeneric) _SPIRV_OP(GenericCastToPtr) +_SPIRV_OP(CrossWorkgroupCastToPtrINTEL) +_SPIRV_OP(PtrCastToCrossWorkgroupINTEL) _SPIRV_OP(Bitcast) _SPIRV_OP(SNegate) _SPIRV_OP(FNegate) diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h index ea00610f0bbd8..2b6b0bc3d0dcf 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h @@ -174,6 +174,8 @@ inline bool isValid(spv::StorageClass V) { case StorageClassPushConstant: case StorageClassAtomicCounter: case StorageClassImage: + case StorageClassDeviceOnlyINTEL: + case StorageClassHostOnlyINTEL: return true; default: return false; @@ -728,6 +730,8 @@ inline bool isValid(spv::Op V) { case OpConvertUToPtr: case OpPtrCastToGeneric: case OpGenericCastToPtr: + case OpPtrCastToCrossWorkgroupINTEL: + case OpCrossWorkgroupCastToPtrINTEL: case OpGenericCastToPtrExplicit: case OpBitcast: case OpSNegate: diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index f6cf432d9f0f4..a1a1d194c45b2 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -150,6 +150,8 @@ template <> inline void SPIRVMap::init() { add(StorageClassPushConstant, "PushConstant"); add(StorageClassAtomicCounter, "AtomicCounter"); add(StorageClassImage, "Image"); + add(StorageClassDeviceOnlyINTEL, "DeviceOnlyINTEL"); + add(StorageClassHostOnlyINTEL, "HostOnlyINTEL"); } SPIRV_DEF_NAMEMAP(StorageClass, SPIRVStorageClassNameMap) @@ -549,6 +551,7 @@ template <> inline void SPIRVMap::init() { add(CapabilityGroupNonUniformShuffleRelative, "GroupNonUniformShuffleRelative"); add(CapabilityGroupNonUniformClustered, "GroupNonUniformClustered"); + add(CapabilityUSMStorageClassesINTEL, "USMStorageClassesINTEL"); } SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCode.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCode.h index f5b2cb937a170..918670e0d3354 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCode.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCode.h @@ -96,7 +96,9 @@ inline bool isCmpOpCode(Op OpCode) { inline bool isCvtOpCode(Op OpCode) { return ((unsigned)OpCode >= OpConvertFToU && (unsigned)OpCode <= OpBitcast) || - OpCode == OpSatConvertSToU || OpCode == OpSatConvertUToS; + OpCode == OpSatConvertSToU || OpCode == OpSatConvertUToS || + OpCode == OpPtrCastToCrossWorkgroupINTEL || + OpCode == OpCrossWorkgroupCastToPtrINTEL; } inline bool isCvtToUnsignedOpCode(Op OpCode) { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h index a0e6643b98f0d..ceaad8ec5a695 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h @@ -469,6 +469,8 @@ _SPIRV_OP(SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 5814) _SPIRV_OP(SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 5815) _SPIRV_OP(SubgroupAvcSicGetInterRawSadsINTEL, 5816) _SPIRV_OP(LoopControlINTEL, 5887) +_SPIRV_OP(PtrCastToCrossWorkgroupINTEL, 5934) +_SPIRV_OP(CrossWorkgroupCastToPtrINTEL, 5938) _SPIRV_OP(ReadPipeBlockingINTEL, 5946) _SPIRV_OP(WritePipeBlockingINTEL, 5947) _SPIRV_OP(FPGARegINTEL, 5949) diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp b/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp index 0c5477cfdf6eb..bb2f1f3161382 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp @@ -196,6 +196,8 @@ enum StorageClass { StorageClassShaderRecordBufferNV = 5343, StorageClassPhysicalStorageBuffer = 5349, StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassDeviceOnlyINTEL = 5936, + StorageClassHostOnlyINTEL = 5937, StorageClassMax = 0x7fffffff, }; @@ -953,6 +955,7 @@ enum Capability { CapabilityFPGARegINTEL = 5948, CapabilityKernelAttributesINTEL = 5892, CapabilityFPGAKernelAttributesINTEL = 5897, + CapabilityUSMStorageClassesINTEL = 5935, CapabilityIOPipeINTEL = 5943, CapabilityMax = 0x7fffffff, }; @@ -1493,6 +1496,8 @@ enum Op { OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, OpLoopControlINTEL = 5887, + OpPtrCastToCrossWorkgroupINTEL = 5934, + OpCrossWorkgroupCastToPtrINTEL = 5938, OpReadPipeBlockingINTEL = 5946, OpWritePipeBlockingINTEL = 5947, OpFPGARegINTEL = 5949, diff --git a/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll b/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll new file mode 100644 index 0000000000000..457222be9c372 --- /dev/null +++ b/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll @@ -0,0 +1,223 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_usm_storage_classes -o %t.spv +; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-EXT +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NO-EXT +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM-NO-USM + +; CHECK-SPIRV-EXT: Capability USMStorageClassesINTEL +; CHECK-SPIRV-NO-EXT-NO: Capability USMStorageClassesINTEL +; CHECK-SPIRV: Name [[DEVICE:[0-9]+]] "DEVICE" +; CHECK-SPIRV: Name [[HOST:[0-9]+]] "HOST" +; CHECK-SPIRV: Name [[GLOB_ARG1:[0-9]+]] "arg_glob.addr" +; CHECK-SPIRV: Name [[DEVICE_ARG1:[0-9]+]] "arg_dev.addr" +; CHECK-SPIRV: Name [[GLOB_ARG2:[0-9]+]] "arg_glob.addr" +; CHECK-SPIRV: Name [[HOST_ARG1:[0-9]+]] "arg_host.addr" +; CHECK-SPIRV: Name [[GLOB_ARG3:[0-9]+]] "arg_glob.addr" +; CHECK-SPIRV: Name [[DEVICE_ARG2:[0-9]+]] "arg_dev.addr" +; CHECK-SPIRV: Name [[GLOB_ARG4:[0-9]+]] "arg_glob.addr" +; CHECK-SPIRV: Name [[HOST_ARG2:[0-9]+]] "arg_host.addr" +; CHECK-SPIRV-EXT: TypePointer [[DEVICE_TY:[0-9]+]] 5936 {{[0-9]+}} +; CHECK-SPIRV-EXT: TypePointer [[HOST_TY:[0-9]+]] 5937 {{[0-9]+}} +; CHECK-SPIRV-NO-EXT: TypePointer [[DEVICE_TY:[0-9]+]] 5 {{[0-9]+}} +; CHECK-SPIRV-NO-EXT: TypePointer [[HOST_TY:[0-9]+]] 5 {{[0-9]+}} +; CHECK-SPIRV: Load [[DEVICE_TY]] {{[0-9]+}} [[DEVICE]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV: Load [[HOST_TY]] {{[0-9]+}} [[HOST]] {{[0-9]+}} {{[0-9]+}} + +; ModuleID = 'intel_usm_addrspaces.cpp' +source_filename = "intel_usm_addrspaces.cpp" +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +target triple = "spir64-unknown-unknown-sycldevice" + +%"class._ZTSZ4mainE3$_0.anon" = type { i8 } + +; Function Attrs: norecurse nounwind +define spir_kernel void @_ZTSZ4mainE11fake_kernel() #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !4 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !4 { +entry: + %0 = alloca %"class._ZTSZ4mainE3$_0.anon", align 1 + %1 = bitcast %"class._ZTSZ4mainE3$_0.anon"* %0 to i8* + call void @llvm.lifetime.start.p0i8(i64 1, i8* %1) #4 + %2 = addrspacecast %"class._ZTSZ4mainE3$_0.anon"* %0 to %"class._ZTSZ4mainE3$_0.anon" addrspace(4)* + call spir_func void @"_ZZ4mainENK3$_0clEv"(%"class._ZTSZ4mainE3$_0.anon" addrspace(4)* %2) + %3 = bitcast %"class._ZTSZ4mainE3$_0.anon"* %0 to i8* + call void @llvm.lifetime.end.p0i8(i64 1, i8* %3) #4 + ret void +} + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 + +; Function Attrs: inlinehint norecurse nounwind +define internal spir_func void @"_ZZ4mainENK3$_0clEv"(%"class._ZTSZ4mainE3$_0.anon" addrspace(4)* %this) #2 align 2 { +entry: + %this.addr = alloca %"class._ZTSZ4mainE3$_0.anon" addrspace(4)*, align 8 + store %"class._ZTSZ4mainE3$_0.anon" addrspace(4)* %this, %"class._ZTSZ4mainE3$_0.anon" addrspace(4)** %this.addr, align 8, !tbaa !5 + call spir_func void @_Z6usagesv() + ret void +} + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 + +; Function Attrs: norecurse nounwind +define spir_func void @_Z6usagesv() #3 { +entry: +; CHECK-LLVM: %DEVICE = alloca i32 addrspace(5)*, align 8 +; CHECK-LLVM-NO-USM: %DEVICE = alloca i32 addrspace(1)*, align 8 + %DEVICE = alloca i32 addrspace(5)*, align 8 + +; CHECK-LLVM: %HOST = alloca i32 addrspace(6)*, align 8 +; CHECK-LLVM-NO-USM: %HOST = alloca i32 addrspace(1)*, align 8 + %HOST = alloca i32 addrspace(6)*, align 8 + +; CHECK-LLVM: bitcast i32 addrspace(5)** %DEVICE to i8* +; CHECK-LLVM-NO-USM: bitcast i32 addrspace(1)** %DEVICE to i8* + %0 = bitcast i32 addrspace(5)** %DEVICE to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* %0) #4 + +; CHECK-LLVM: bitcast i32 addrspace(6)** %HOST to i8* +; CHECK-LLVM-NO-USM: bitcast i32 addrspace(1)** %HOST to i8* + %1 = bitcast i32 addrspace(6)** %HOST to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) #4 + +; CHECK-LLVM: %[[DLOAD_E:[0-9]+]] = load i32 addrspace(5)*, i32 addrspace(5)** %DEVICE, align 8 +; CHECK-LLVM-NO-USM: %[[DLOAD_NE:[0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)** %DEVICE, align 8 + %2 = load i32 addrspace(5)*, i32 addrspace(5)** %DEVICE, align 8, !tbaa !5 + +; CHECK-LLVM: addrspacecast i32 addrspace(5)* %[[DLOAD_E]] to i32 addrspace(4)* +; CHECK-LLVM-NO-USM: addrspacecast i32 addrspace(1)* %[[DLOAD_NE]] to i32 addrspace(4)* + %3 = addrspacecast i32 addrspace(5)* %2 to i32 addrspace(4)* + call spir_func void @_Z3fooPi(i32 addrspace(4)* %3) + +; CHECK-LLVM: %[[HLOAD_E:[0-9]+]] = load i32 addrspace(6)*, i32 addrspace(6)** %HOST, align 8 +; CHECK-LLVM-NO-USM: %[[HLOAD_NE:[0-9]+]] = load i32 addrspace(1)*, i32 addrspace(1)** %HOST, align 8 + %4 = load i32 addrspace(6)*, i32 addrspace(6)** %HOST, align 8, !tbaa !5 + +; CHECK-LLVM: addrspacecast i32 addrspace(6)* %[[HLOAD_E]] to i32 addrspace(4)* +; CHECK-LLVM-NO-USM: addrspacecast i32 addrspace(1)* %[[HLOAD_NE]] to i32 addrspace(4)* + %5 = addrspacecast i32 addrspace(6)* %4 to i32 addrspace(4)* + call spir_func void @_Z3fooPi(i32 addrspace(4)* %5) + +; CHECK-LLVM: bitcast i32 addrspace(6)** %HOST to i8* +; CHECK-LLVM-NO-USM: bitcast i32 addrspace(1)** %HOST to i8* + %6 = bitcast i32 addrspace(6)** %HOST to i8* + call void @llvm.lifetime.end.p0i8(i64 8, i8* %6) #4 + +; CHECK-LLVM: bitcast i32 addrspace(5)** %DEVICE to i8* +; CHECK-LLVM-NO-USM: bitcast i32 addrspace(1)** %DEVICE to i8* + %7 = bitcast i32 addrspace(5)** %DEVICE to i8* + call void @llvm.lifetime.end.p0i8(i64 8, i8* %7) #4 + + ret void +} + +; Function Attrs: norecurse nounwind +define spir_func void @_Z3fooPi(i32 addrspace(4)* %Data) #3 { +entry: + %Data.addr = alloca i32 addrspace(4)*, align 8 + store i32 addrspace(4)* %Data, i32 addrspace(4)** %Data.addr, align 8, !tbaa !5 + ret void +} + +; CHECK-SPIRV: Load {{[0-9]+}} [[CAST_FROM1:[0-9]+]] [[GLOB_ARG1]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-EXT: CrossWorkgroupCastToPtrINTEL {{[0-9]+}} [[CAST_TO1:[0-9]+]] [[CAST_FROM1]] +; CHECK-SPIRV-NO-EXT-NOT: GenericCastToPtr {{[0-9]+}} [[CAST_TO1:[0-9]+]] [[CAST_FROM1]] +; CHECL-SPIRV: Store [[DEVICE_ARG1]] [[CAST_TO1]] {{[0-9]+}} {{[0-9]+}} +; Function Attrs: norecurse nounwind +define spir_func void @_Z3booPii(i32 addrspace(1)* %arg_glob, i32 addrspace(5)* %arg_dev) #3 !kernel_arg_addr_space !9 { +entry: + %arg_glob.addr = alloca i32 addrspace(1)*, align 4 + %arg_dev.addr = alloca i32 addrspace(5)*, align 4 + store i32 addrspace(1)* %arg_glob, i32 addrspace(1)** %arg_glob.addr, align 4 + store i32 addrspace(5)* %arg_dev, i32 addrspace(5)** %arg_dev.addr, align 4 + %0 = load i32 addrspace(1)*, i32 addrspace(1)** %arg_glob.addr, align 4 +; CHECK-LLVM: addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(5)* +; CHECK-LLVM-NO-USM-NOT: addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(5)* + %1 = addrspacecast i32 addrspace(1)* %0 to i32 addrspace(5)* + store i32 addrspace(5)* %1, i32 addrspace(5)** %arg_dev.addr, align 4 + ret void +} + +; CHECK-SPIRV: Load {{[0-9]+}} [[CAST_FROM2:[0-9]+]] [[GLOB_ARG2]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-EXT: CrossWorkgroupCastToPtrINTEL {{[0-9]+}} [[CAST_TO2:[0-9]+]] [[CAST_FROM2]] +; CHECK-SPIRV-NO-EXT-NOT: GenericCastToPtr {{[0-9]+}} [[CAST_TO2:[0-9]+]] [[CAST_FROM2]] +; CHECL-SPIRV: Store [[HOST_ARG1]] [[CAST_TO2]] {{[0-9]+}} {{[0-9]+}} +; Function Attrs: norecurse nounwind +define spir_func void @_Z3gooPii(i32 addrspace(1)* %arg_glob, i32 addrspace(6)* %arg_host) #3 !kernel_arg_addr_space !10 { +entry: + %arg_glob.addr = alloca i32 addrspace(1)*, align 4 + %arg_host.addr = alloca i32 addrspace(6)*, align 4 + store i32 addrspace(1)* %arg_glob, i32 addrspace(1)** %arg_glob.addr, align 4 + store i32 addrspace(6)* %arg_host, i32 addrspace(6)** %arg_host.addr, align 4 + %0 = load i32 addrspace(1)*, i32 addrspace(1)** %arg_glob.addr, align 4 +; CHECK-LLVM: addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(6)* +; CHECK-LLVM-NO-USM-NOT: addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(6)* + %1 = addrspacecast i32 addrspace(1)* %0 to i32 addrspace(6)* + store i32 addrspace(6)* %1, i32 addrspace(6)** %arg_host.addr, align 4 + ret void +} + +; CHECK-SPIRV: Load {{[0-9]+}} [[CAST_FROM3:[0-9]+]] [[DEVICE_ARG2]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-EXT: PtrCastToCrossWorkgroupINTEL {{[0-9]+}} [[CAST_TO3:[0-9]+]] [[CAST_FROM3]] +; CHECK-SPIRV-NO-EXT-NOT: PtrCastToGeneric {{[0-9]+}} [[CAST_TO3:[0-9]+]] [[CAST_FROM3]] +; CHECL-SPIRV: Store [[GLOB_ARG3]] [[CAST_TO3]] {{[0-9]+}} {{[0-9]+}} +; Function Attrs: norecurse nounwind +define spir_func void @_Z3zooPii(i32 addrspace(1)* %arg_glob, i32 addrspace(5)* %arg_dev) #3 !kernel_arg_addr_space !9 { +entry: + %arg_glob.addr = alloca i32 addrspace(1)*, align 4 + %arg_dev.addr = alloca i32 addrspace(5)*, align 4 + store i32 addrspace(1)* %arg_glob, i32 addrspace(1)** %arg_glob.addr, align 4 + store i32 addrspace(5)* %arg_dev, i32 addrspace(5)** %arg_dev.addr, align 4 + %0 = load i32 addrspace(5)*, i32 addrspace(5)** %arg_dev.addr, align 4 +; CHECK-LLVM: addrspacecast i32 addrspace(5)* %{{[0-9]+}} to i32 addrspace(1)* +; CHECK-LLVM-NO-USM-NOT: addrspacecast i32 addrspace(5)* %{{[0-9]+}} to i32 addrspace(1)* + %1 = addrspacecast i32 addrspace(5)* %0 to i32 addrspace(1)* + store i32 addrspace(1)* %1, i32 addrspace(1)** %arg_glob.addr, align 4 + ret void +} + +; CHECK-SPIRV: Load {{[0-9]+}} [[CAST_FROM4:[0-9]+]] [[HOST_ARG2]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-EXT: PtrCastToCrossWorkgroupINTEL {{[0-9]+}} [[CAST_TO4:[0-9]+]] [[CAST_FROM4]] +; CHECK-SPIRV-NO-EXT-NOT: PtrCastToGeneric {{[0-9]+}} [[CAST_TO4:[0-9]+]] [[CAST_FROM4]] +; CHECL-SPIRV: Store [[GLOB_ARG4]] [[CAST_TO4]] {{[0-9]+}} {{[0-9]+}} +; Function Attrs: norecurse nounwind +define spir_func void @_Z3mooPii(i32 addrspace(1)* %arg_glob, i32 addrspace(6)* %arg_host) #3 !kernel_arg_addr_space !10 { +entry: + %arg_glob.addr = alloca i32 addrspace(1)*, align 4 + %arg_host.addr = alloca i32 addrspace(6)*, align 4 + store i32 addrspace(1)* %arg_glob, i32 addrspace(1)** %arg_glob.addr, align 4 + store i32 addrspace(6)* %arg_host, i32 addrspace(6)** %arg_host.addr, align 4 + %0 = load i32 addrspace(6)*, i32 addrspace(6)** %arg_host.addr, align 4 +; CHECK-LLVM: addrspacecast i32 addrspace(6)* %{{[0-9]+}} to i32 addrspace(1)* +; CHECK-LLVM-NO-USM-NOT: addrspacecast i32 addrspace(6)* %{{[0-9]+}} to i32 addrspace(1)* + %1 = addrspacecast i32 addrspace(6)* %0 to i32 addrspace(1)* + store i32 addrspace(1)* %1, i32 addrspace(1)** %arg_glob.addr, align 4 + ret void +} + +attributes #0 = { norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "sycl-module-id"="intel_usm_addrspaces.cpp" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { argmemonly nounwind willreturn } +attributes #2 = { inlinehint norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } + +!llvm.module.flags = !{!0} +!opencl.spir.version = !{!1} +!spirv.Source = !{!2} +!llvm.ident = !{!3} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, i32 2} +!2 = !{i32 4, i32 100000} +!3 = !{!"clang version 11.0.0"} +!4 = !{} +!5 = !{!6, !6, i64 0} +!6 = !{!"any pointer", !7, i64 0} +!7 = !{!"omnipotent char", !8, i64 0} +!8 = !{!"Simple C++ TBAA"} +!9 = !{i32 1, i32 5} +!10 = !{i32 1, i32 6}