diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index f4daab7d06eb5..de0b97fbea0c1 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -243,11 +243,8 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, continue; MetadataAsValue *VMD = cast(II->getOperand(1)); - Type *ElementTy = cast(VMD->getMetadata())->getType(); - if (isUntypedPointerTy(ElementTy)) - ElementTy = - TypedPointerType::get(IntegerType::getInt8Ty(II->getContext()), - getPointerAddressSpace(ElementTy)); + Type *ElementTy = + toTypedPointer(cast(VMD->getMetadata())->getType()); SPIRVType *ElementType = GR->getOrCreateSPIRVType(ElementTy, MIRBuilder); return GR->getOrCreateSPIRVPointerType( ElementType, MIRBuilder, @@ -257,12 +254,8 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, // Replace PointerType with TypedPointerType to be able to map SPIR-V types to // LLVM types in a consistent manner - if (isUntypedPointerTy(OriginalArgType)) { - OriginalArgType = - TypedPointerType::get(Type::getInt8Ty(F.getContext()), - getPointerAddressSpace(OriginalArgType)); - } - return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual); + return GR->getOrCreateSPIRVType(toTypedPointer(OriginalArgType), MIRBuilder, + ArgAccessQual); } static SPIRV::ExecutionModel::ExecutionModel @@ -386,8 +379,8 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, Type *FRetTy = FTy->getReturnType(); if (isUntypedPointerTy(FRetTy)) { if (Type *FRetElemTy = GR->findDeducedElementType(&F)) { - TypedPointerType *DerivedTy = - TypedPointerType::get(FRetElemTy, getPointerAddressSpace(FRetTy)); + TypedPointerType *DerivedTy = TypedPointerType::get( + toTypedPointer(FRetElemTy), getPointerAddressSpace(FRetTy)); GR->addReturnType(&F, DerivedTy); FRetTy = DerivedTy; } diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index bbd25dc85f52b..7b8e3230bf553 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -50,6 +50,13 @@ void initializeSPIRVEmitIntrinsicsPass(PassRegistry &); } // namespace llvm namespace { + +inline MetadataAsValue *buildMD(Value *Arg) { + LLVMContext &Ctx = Arg->getContext(); + return MetadataAsValue::get( + Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(Arg))); +} + class SPIRVEmitIntrinsics : public ModulePass, public InstVisitor { @@ -84,12 +91,9 @@ class SPIRVEmitIntrinsics CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef Types, Value *Arg, Value *Arg2, ArrayRef Imms, IRBuilder<> &B) { - ConstantAsMetadata *CM = ValueAsMetadata::getConstant(Arg); - MDTuple *TyMD = MDNode::get(F->getContext(), CM); - MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); SmallVector Args; Args.push_back(Arg2); - Args.push_back(VMD); + Args.push_back(buildMD(Arg)); for (auto *Imm : Imms) Args.push_back(Imm); return B.CreateIntrinsic(IntrID, {Types}, Args); @@ -228,20 +232,23 @@ void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty, void SPIRVEmitIntrinsics::buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg) { Value *OfType = PoisonValue::get(ElemTy); - CallInst *AssignPtrTyCI = buildIntrWithMD( - Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg, - {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B); - GR->addDeducedElementType(AssignPtrTyCI, ElemTy); - GR->addDeducedElementType(Arg, ElemTy); - GR->addAssignPtrTypeInstr(Arg, AssignPtrTyCI); + CallInst *AssignPtrTyCI = GR->findAssignPtrTypeInstr(Arg); + if (AssignPtrTyCI == nullptr || + AssignPtrTyCI->getParent()->getParent() != F) { + AssignPtrTyCI = buildIntrWithMD( + Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg, + {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B); + GR->addDeducedElementType(AssignPtrTyCI, ElemTy); + GR->addDeducedElementType(Arg, ElemTy); + GR->addAssignPtrTypeInstr(Arg, AssignPtrTyCI); + } else { + updateAssignType(AssignPtrTyCI, Arg, OfType); + } } void SPIRVEmitIntrinsics::updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType) { - LLVMContext &Ctx = Arg->getContext(); - AssignCI->setArgOperand( - 1, MetadataAsValue::get( - Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType)))); + AssignCI->setArgOperand(1, buildMD(OfType)); if (cast(AssignCI)->getIntrinsicID() != Intrinsic::spv_assign_ptr_type) return; @@ -560,9 +567,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) { B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca()); } SmallVector Types = {OpTy, OpTy}; - MetadataAsValue *VMD = MetadataAsValue::get( - Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OpTyVal))); - SmallVector Args = {Op, VMD, + SmallVector Args = {Op, buildMD(OpTyVal), B.getInt32(getPointerAddressSpace(OpTy))}; CallInst *PtrCastI = B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args); @@ -689,8 +694,7 @@ Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) { Constant *TyC = UndefValue::get(IA->getFunctionType()); MDString *ConstraintString = MDString::get(Ctx, IA->getConstraintString()); SmallVector Args = { - MetadataAsValue::get(Ctx, - MDNode::get(Ctx, ValueAsMetadata::getConstant(TyC))), + buildMD(TyC), MetadataAsValue::get(Ctx, MDNode::get(Ctx, ConstraintString))}; for (unsigned OpIdx = 0; OpIdx < Call.arg_size(); OpIdx++) Args.push_back(Call.getArgOperand(OpIdx)); @@ -822,12 +826,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( return; setInsertPointSkippingPhis(B, I); - Constant *ExpectedElementTypeConst = - Constant::getNullValue(ExpectedElementType); - ConstantAsMetadata *CM = - ValueAsMetadata::getConstant(ExpectedElementTypeConst); - MDTuple *TyMD = MDNode::get(F->getContext(), CM); - MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); + MetadataAsValue *VMD = buildMD(PoisonValue::get(ExpectedElementType)); unsigned AddressSpace = getPointerAddressSpace(Pointer->getType()); bool FirstPtrCastOrAssignPtrType = true; @@ -873,12 +872,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( // spv_assign_ptr_type instead. if (FirstPtrCastOrAssignPtrType && (isa(Pointer) || isa(Pointer))) { - CallInst *CI = buildIntrWithMD( - Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, - ExpectedElementTypeConst, Pointer, {B.getInt32(AddressSpace)}, B); - GR->addDeducedElementType(CI, ExpectedElementType); - GR->addDeducedElementType(Pointer, ExpectedElementType); - GR->addAssignPtrTypeInstr(Pointer, CI); + buildAssignPtr(B, ExpectedElementType, Pointer); return; } @@ -1167,12 +1161,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I, setInsertPointAfterDef(B, I); Type *ElemTy = deduceElementType(I); - Constant *EltTyConst = UndefValue::get(ElemTy); - unsigned AddressSpace = getPointerAddressSpace(I->getType()); - CallInst *CI = buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, - EltTyConst, I, {B.getInt32(AddressSpace)}, B); - GR->addDeducedElementType(CI, ElemTy); - GR->addAssignPtrTypeInstr(I, CI); + buildAssignPtr(B, ElemTy, I); } void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I, @@ -1407,12 +1396,14 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { continue; insertAssignPtrTypeIntrs(I, B); - deduceOperandElementType(I); insertAssignTypeIntrs(I, B); insertPtrCastOrAssignTypeInstr(I, B); insertSpirvDecorations(I, B); } + for (auto &I : instructions(Func)) + deduceOperandElementType(&I); + for (auto *I : Worklist) { TrackConstants = true; if (!I->getType()->isVoidTy() || isa(I)) diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp index f96c3a2b0a770..d434e0b5efbcc 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -742,8 +742,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty, bool EmitIR) { SmallVector FieldTypes; for (const auto &Elem : Ty->elements()) { - SPIRVType *ElemTy = - findSPIRVType(toTypedPointer(Elem, Ty->getContext()), MIRBuilder); + SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder); assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid && "Invalid struct element type"); FieldTypes.push_back(getSPIRVTypeID(ElemTy)); diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 517a9b490ebad..db83172f7fa9c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1086,7 +1086,11 @@ bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg, // don't generate a cast between identical storage classes if (SrcSC == DstSC) - return true; + return BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(TargetOpcode::COPY)) + .addDef(ResVReg) + .addUse(SrcPtr) + .constrainAllUses(TII, TRI, RBI); // Casting from an eligible pointer to Generic. if (DstSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(SrcSC)) @@ -1121,10 +1125,13 @@ bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg, if (SrcSC == SPIRV::StorageClass::CrossWorkgroup && isUSMStorageClass(DstSC)) return selectUnOp(ResVReg, ResType, I, SPIRV::OpCrossWorkgroupCastToPtrINTEL); + if (isUSMStorageClass(SrcSC) && DstSC == SPIRV::StorageClass::Generic) + return selectUnOp(ResVReg, ResType, I, SPIRV::OpPtrCastToGeneric); + if (SrcSC == SPIRV::StorageClass::Generic && isUSMStorageClass(DstSC)) + return selectUnOp(ResVReg, ResType, I, SPIRV::OpGenericCastToPtr); - // TODO Should this case just be disallowed completely? - // We're casting 2 other arbitrary address spaces, so have to bitcast. - return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast); + // Bitcast for pointers requires that the address spaces must match + return false; } static unsigned getFCmpOpcode(unsigned PredNum) { diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 61f99f8d85269..30a6c474f467a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -95,7 +95,7 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, if (ReqCaps.size() == 1) { auto Cap = ReqCaps[0]; if (Reqs.isCapabilityAvailable(Cap)) - return {true, {Cap}, {}, ReqMinVer, ReqMaxVer}; + return {true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer}; } else { // By SPIR-V specification: "If an instruction, enumerant, or other // feature specifies multiple enabling capabilities, only one such @@ -110,7 +110,7 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, for (size_t i = 0, Sz = UseCaps.size(); i < Sz; ++i) { auto Cap = UseCaps[i]; if (i == Sz - 1 || !AvoidCaps.S.contains(Cap)) - return {true, {Cap}, {}, ReqMinVer, ReqMaxVer}; + return {true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer}; } } } diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp index a0a253c23b1e8..adc5b36af6f18 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -166,8 +166,8 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, } Register Def = MI.getOperand(0).getReg(); Register Source = MI.getOperand(2).getReg(); - SPIRVType *BaseTy = GR->getOrCreateSPIRVType( - getMDOperandAsType(MI.getOperand(3).getMetadata(), 0), MIB); + Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0); + SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElemTy, MIB); SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType( BaseTy, MI, *MF.getSubtarget().getInstrInfo(), addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST)); @@ -220,7 +220,7 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, MIB.setInsertPt(*MI->getParent(), MI); const GlobalValue *Global = MI->getOperand(1).getGlobal(); Type *ElementTy = GR->getDeducedGlobalValueType(Global); - auto *Ty = TypedPointerType::get(ElementTy, + auto *Ty = TypedPointerType::get(toTypedPointer(ElementTy), Global->getType()->getAddressSpace()); SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB); break; @@ -409,8 +409,8 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) { Register Reg = MI.getOperand(1).getReg(); MIB.setInsertPt(*MI.getParent(), MI.getIterator()); - SPIRVType *BaseTy = GR->getOrCreateSPIRVType( - getMDOperandAsType(MI.getOperand(2).getMetadata(), 0), MIB); + Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0); + SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElementTy, MIB); SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType( BaseTy, MI, *MF.getSubtarget().getInstrInfo(), addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST)); @@ -453,6 +453,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, Ty = TargetExtIt == TargetExtConstTypes.end() ? MI.getOperand(1).getCImm()->getType() : TargetExtIt->second; + GR->add(MI.getOperand(1).getCImm(), &MF, Reg); } else if (MIOp == TargetOpcode::G_FCONSTANT) { Ty = MI.getOperand(1).getFPImm()->getType(); } else { diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 65b48c8acf6ab..318c5cebb7a43 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -689,34 +689,34 @@ class StorageClass value> { bits<32> Value = value; } -multiclass StorageClassOperand value, list reqCapabilities> { +multiclass StorageClassOperand value, list reqExtensions, list reqCapabilities> { def : StorageClass; - defm : SymbolicOperandWithRequirements; -} - -defm UniformConstant : StorageClassOperand<0, []>; -defm Input : StorageClassOperand<1, []>; -defm Uniform : StorageClassOperand<2, [Shader]>; -defm Output : StorageClassOperand<3, [Shader]>; -defm Workgroup : StorageClassOperand<4, []>; -defm CrossWorkgroup : StorageClassOperand<5, []>; -defm Private : StorageClassOperand<6, [Shader]>; -defm Function : StorageClassOperand<7, []>; -defm Generic : StorageClassOperand<8, [GenericPointer]>; -defm PushConstant : StorageClassOperand<9, [Shader]>; -defm AtomicCounter : StorageClassOperand<10, [AtomicStorage]>; -defm Image : StorageClassOperand<11, []>; -defm StorageBuffer : StorageClassOperand<12, [Shader]>; -defm CallableDataNV : StorageClassOperand<5328, [RayTracingNV]>; -defm IncomingCallableDataNV : StorageClassOperand<5329, [RayTracingNV]>; -defm RayPayloadNV : StorageClassOperand<5338, [RayTracingNV]>; -defm HitAttributeNV : StorageClassOperand<5339, [RayTracingNV]>; -defm IncomingRayPayloadNV : StorageClassOperand<5342, [RayTracingNV]>; -defm ShaderRecordBufferNV : StorageClassOperand<5343, [RayTracingNV]>; -defm PhysicalStorageBufferEXT : StorageClassOperand<5349, [PhysicalStorageBufferAddressesEXT]>; -defm CodeSectionINTEL : StorageClassOperand<5605, [FunctionPointersINTEL]>; -defm DeviceOnlyINTEL : StorageClassOperand<5936, [USMStorageClassesINTEL]>; -defm HostOnlyINTEL : StorageClassOperand<5937, [USMStorageClassesINTEL]>; + defm : SymbolicOperandWithRequirements; +} + +defm UniformConstant : StorageClassOperand<0, [], []>; +defm Input : StorageClassOperand<1, [], []>; +defm Uniform : StorageClassOperand<2, [], [Shader]>; +defm Output : StorageClassOperand<3, [], [Shader]>; +defm Workgroup : StorageClassOperand<4, [], []>; +defm CrossWorkgroup : StorageClassOperand<5, [], []>; +defm Private : StorageClassOperand<6, [], [Shader]>; +defm Function : StorageClassOperand<7, [], []>; +defm Generic : StorageClassOperand<8, [], [GenericPointer]>; +defm PushConstant : StorageClassOperand<9, [], [Shader]>; +defm AtomicCounter : StorageClassOperand<10, [], [AtomicStorage]>; +defm Image : StorageClassOperand<11, [], []>; +defm StorageBuffer : StorageClassOperand<12, [], [Shader]>; +defm CallableDataNV : StorageClassOperand<5328, [], [RayTracingNV]>; +defm IncomingCallableDataNV : StorageClassOperand<5329, [], [RayTracingNV]>; +defm RayPayloadNV : StorageClassOperand<5338, [], [RayTracingNV]>; +defm HitAttributeNV : StorageClassOperand<5339, [], [RayTracingNV]>; +defm IncomingRayPayloadNV : StorageClassOperand<5342, [], [RayTracingNV]>; +defm ShaderRecordBufferNV : StorageClassOperand<5343, [], [RayTracingNV]>; +defm PhysicalStorageBufferEXT : StorageClassOperand<5349, [], [PhysicalStorageBufferAddressesEXT]>; +defm CodeSectionINTEL : StorageClassOperand<5605, [SPV_INTEL_function_pointers], [FunctionPointersINTEL]>; +defm DeviceOnlyINTEL : StorageClassOperand<5936, [SPV_INTEL_usm_storage_classes], [USMStorageClassesINTEL]>; +defm HostOnlyINTEL : StorageClassOperand<5937, [SPV_INTEL_usm_storage_classes], [USMStorageClassesINTEL]>; //===----------------------------------------------------------------------===// // Multiclass used to define Dim enum values and at the same time diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index c20f3546a3e55..c1b90b0e9d884 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -280,7 +280,7 @@ bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID) { Type *getMDOperandAsType(const MDNode *N, unsigned I) { Type *ElementTy = cast(N->getOperand(I))->getType(); - return toTypedPointer(ElementTy, N->getContext()); + return toTypedPointer(ElementTy); } // The set of names is borrowed from the SPIR-V translator. diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index 33cb509dc4a59..c131eecb1c137 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -113,7 +113,7 @@ inline bool isTypedPointerTy(const Type *T) { // True if this is an instance of PointerType. inline bool isUntypedPointerTy(const Type *T) { - return T->getTypeID() == Type::PointerTyID; + return T && T->getTypeID() == Type::PointerTyID; } // True if this is an instance of PointerType or TypedPointerType. @@ -153,9 +153,9 @@ inline Type *reconstructFunctionType(Function *F) { return FunctionType::get(F->getReturnType(), ArgTys, F->isVarArg()); } -inline Type *toTypedPointer(Type *Ty, LLVMContext &Ctx) { +inline Type *toTypedPointer(Type *Ty) { return isUntypedPointerTy(Ty) - ? TypedPointerType::get(IntegerType::getInt8Ty(Ctx), + ? TypedPointerType::get(IntegerType::getInt8Ty(Ty->getContext()), getPointerAddressSpace(Ty)) : Ty; } diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll index b5df462bd8fa9..986d88da41832 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll @@ -1,9 +1,9 @@ ; Modified from: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/test/extensions/INTEL/SPV_INTEL_usm_storage_classes/intel_usm_addrspaces.ll ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-EXT -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - -filetype=obj | spirv-val %} ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-WITHOUT -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-: Capability USMStorageClassesINTEL ; CHECK-SPIRV-WITHOUT-NO: Capability USMStorageClassesINTEL diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll index 8d34a40326d70..0e2b26c83bcdd 100644 --- a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll +++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll @@ -5,7 +5,7 @@ define spir_kernel void @test_pointer_cast(ptr addrspace(1) %src) { ; CHECK-NOT: call{{.*}} void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i8 undef, i32 1) -; CHECK: call{{.*}} void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i32 0, i32 1) +; CHECK: call{{.*}} void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i32 poison, i32 1) %b = bitcast ptr addrspace(1) %src to ptr addrspace(1) %g = getelementptr inbounds i32, ptr addrspace(1) %b, i64 52 ret void diff --git a/llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll b/llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll new file mode 100644 index 0000000000000..8e70bef3a5399 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll @@ -0,0 +1,26 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: %[[#Char:]] = OpTypeInt 8 0 +; CHECK: %[[#Ptr:]] = OpTypePointer Generic %[[#Char]] +; CHECK: %[[#TypeDef:]] = OpTypePointer Generic %[[#Ptr]] +; CHECK-NOT: %[[#TypeDef]] = OpTypePointer Generic %[[#Ptr]] + +%Range = type { %Array } +%Array = type { [1 x i64] } + +define spir_func ptr addrspace(4) @foo(ptr addrspace(4) dereferenceable_or_null(32) %this) { +entry: + %addr = alloca ptr addrspace(4) + store ptr addrspace(4) %this, ptr %addr + %arrayidx = getelementptr inbounds ptr addrspace(4), ptr addrspace(1) null, i64 0 + %r = addrspacecast ptr addrspace(1) %arrayidx to ptr addrspace(4) + ret ptr addrspace(4) %r +} + +define spir_func void @bar() { +entry: + %retval = alloca ptr addrspace(4) + %retval.ascast = addrspacecast ptr %retval to ptr addrspace(4) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll new file mode 100644 index 0000000000000..e6130cedf6800 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll @@ -0,0 +1,27 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: %[[#Char:]] = OpTypeInt 8 0 +; CHECK-SPIRV-DAG: %[[#ArrayTy:]] = OpTypeArray %[[#Char]] %[[#]] +; CHECK-SPIRV-DAG: %[[#CharPtrTy:]] = OpTypePointer CrossWorkgroup %[[#Char]] +; CHECK-SPIRV-DAG: %[[#Const1:]] = OpConstantComposite %[[#]] %[[#]] %[[#]] +; CHECK-SPIRV-DAG: %[[#CharPtrPtrTy:]] = OpTypePointer CrossWorkgroup %[[#CharPtrTy]] +; CHECK-SPIRV-DAG: %[[#PtrArrayTy:]] = OpTypePointer CrossWorkgroup %[[#ArrayTy]] +; CHECK-SPIRV-DAG: OpVariable %[[#PtrArrayTy]] CrossWorkgroup %[[#Const1]] +; CHECK-SPIRV-DAG: OpVariable %[[#CharPtrPtrTy]] CrossWorkgroup %[[#]] + +@a_var = addrspace(1) global [2 x i8] c"\01\01" +@p_var = addrspace(1) global ptr addrspace(1) getelementptr inbounds ([2 x i8], ptr addrspace(1) @a_var, i32 0, i64 1) + +define spir_func zeroext i8 @foo() { +entry: + ret i8 1 +} + +define spir_func zeroext i8 @bar() { +entry: + ret i8 1 +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll new file mode 100644 index 0000000000000..ab7f923797f30 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll @@ -0,0 +1,65 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - --translator-compatibility-mode | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-COMPAT,CHECK-COMPAT64 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-DEFVER +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - --translator-compatibility-mode | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-COMPAT,CHECK-COMPAT32 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: %[[#CharTy:]] = OpTypeInt 8 0 +; CHECK-SPIRV-DAG: %[[#IntTy:]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[#IntConst1:]] = OpConstant %[[#IntTy]] 1 +; CHECK-SPIRV-DAG: %[[#ArrTy:]] = OpTypeArray %[[#IntTy]] %[[#IntConst1]] +; CHECK-SPIRV-DAG: %[[#BoolTy:]] = OpTypeBool +; CHECK-SPIRV-DAG: %[[#LongTy:]] = OpTypeInt 64 0 +; CHECK-SPIRV-DAG: %[[#LongConst4:]] = OpConstant %[[#LongTy]] 4 +; CHECK-SPIRV-DAG: %[[#IntConst123:]] = OpConstant %[[#IntTy]] 123 +; CHECK-SPIRV-DAG: %[[#CharPtrTy:]] = OpTypePointer Function %[[#CharTy]] +; CHECK-SPIRV-DAG: %[[#ArrPtrTy:]] = OpTypePointer Function %[[#ArrTy]] +; CHECK-SPIRV-DAG: %[[#IntPtrTy:]] = OpTypePointer Function %[[#IntTy]] +; CHECK-SPIRV: OpFunction +; CHECK-SPIRV: %[[#LblEntry:]] = OpLabel +; CHECK-SPIRV: %[[#Value:]] = OpVariable %[[#ArrPtrTy]] Function +; CHECK-SPIRV: %[[#ValueAsCharPtr:]] = OpBitcast %[[#CharPtrTy]] %[[#Value]] +; CHECK-SPIRV: %[[#Eof:]] = OpInBoundsPtrAccessChain %[[#CharPtrTy]] %[[#ValueAsCharPtr]] %[[#LongConst4]] +; CHECK-SPIRV: %[[#EofAsArray:]] = OpBitcast %[[#ArrPtrTy]] %[[#Eof]] +; CHECK-SPIRV: OpBranch %[[#LblCond:]] +; CHECK-SPIRV: %[[#LblCond]] = OpLabel +; CHECK-SPIRV: %[[#Iter:]] = OpPhi %[[#ArrPtrTy]] %[[#Value]] %[[#LblEntry]] %[[#CurrValue:]] %[[#LblBody:]] +; CHECK-COMPAT64: %[[#IterInt:]] = OpConvertPtrToU %[[#LongTy]] %[[#Iter]] +; CHECK-COMPAT64: %[[#EofInt:]] = OpConvertPtrToU %[[#LongTy]] %[[#EofAsArray]] +; CHECK-COMPAT32: %[[#IterInt:]] = OpConvertPtrToU %[[#IntTy]] %[[#Iter]] +; CHECK-COMPAT32: %[[#EofInt:]] = OpConvertPtrToU %[[#IntTy]] %[[#EofAsArray]] +; CHECK-COMPAT: %[[#Is:]] = OpIEqual %[[#BoolTy]] %[[#IterInt]] %[[#EofInt]] +; CHECK-DEFVER: %[[#Is:]] = OpPtrEqual %[[#BoolTy]] %[[#Iter]] %[[#EofAsArray]] +; CHECK-SPIRV: OpBranchConditional %[[#Is]] %[[#LblExit:]] %[[#LblBody]] +; CHECK-SPIRV: %[[#LblBody]] = OpLabel +; CHECK-SPIRV: %[[#IterAsIntPtr:]] = OpBitcast %[[#IntPtrTy]] %[[#Iter]] +; CHECK-SPIRV: OpStore %[[#IterAsIntPtr]] %[[#IntConst123]] Aligned 4 +; CHECK-SPIRV: %[[#IterAsCharPtr:]] = OpBitcast %[[#CharPtrTy]] %[[#Iter]] +; CHECK-SPIRV: %[[#CurrValueAsCharPtr:]] = OpInBoundsPtrAccessChain %[[#CharPtrTy]] %[[#IterAsCharPtr]] %[[#LongConst4]] +; CHECK-SPIRV: %[[#CurrValue]] = OpBitcast %[[#ArrPtrTy]] %[[#CurrValueAsCharPtr]] +; CHECK-SPIRV: OpBranch %[[#LblCond]] +; CHECK-SPIRV: %[[#LblExit]] = OpLabel +; CHECK-SPIRV: OpFunctionEnd + +define spir_kernel void @foo() { +entry: + %v = alloca [1 x i32], align 4 + %eof = getelementptr inbounds i8, ptr %v, i64 4 + br label %cond + +cond: + %iter = phi ptr [ %v, %entry ], [ %curr, %body ] + %is = icmp eq ptr %iter, %eof + br i1 %is, label %exit, label %body + +body: + store i32 123, ptr %iter, align 4 + %curr = getelementptr inbounds i8, ptr %iter, i64 4 + br label %cond + +exit: + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/transcoding/bitcast-diff-addrspace.ll b/llvm/test/CodeGen/SPIRV/transcoding/bitcast-diff-addrspace.ll new file mode 100644 index 0000000000000..c1ef3041c4ce5 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/transcoding/bitcast-diff-addrspace.ll @@ -0,0 +1,44 @@ +; Check that bitcast for pointers implies that the address spaces must match. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_INTEL_usm_storage_classes -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_INTEL_usm_storage_classes -o - -filetype=obj | spirv-val %} + +; CHECK: Capability USMStorageClassesINTEL +; CHECK: OpExtension "SPV_INTEL_usm_storage_classes" +; CHECK-DAG: OpName %[[#Bar:]] "bar" +; CHECK-DAG: %[[#Void:]] = OpTypeVoid +; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0 +; CHECK-DAG: %[[#GenPtrChar:]] = OpTypePointer Generic %[[#Char]] +; CHECK-DAG: %[[#AtDevice:]] = OpTypePointer DeviceOnlyINTEL %[[#Char]] +; CHECK-DAG: %[[#AtHost:]] = OpTypePointer HostOnlyINTEL %[[#Char]] +; CHECK-DAG: %[[#PtrVarHost:]] = OpTypePointer Function %[[#AtHost]] +; CHECK-DAG: %[[#PtrVarDevice:]] = OpTypePointer Function %[[#AtDevice]] +; CHECK: OpFunction +; CHECK: %[[#VarDevice:]] = OpVariable %[[#PtrVarDevice]] Function +; CHECK: %[[#VarHost:]] = OpVariable %[[#PtrVarHost]] Function +; CHECK: %[[#LoadedDevice:]] = OpLoad %[[#AtDevice]] %[[#VarDevice]] +; CHECK: %[[#CastedFromDevice:]] = OpPtrCastToGeneric %[[#GenPtrChar]] %[[#LoadedDevice]] +; CHECK: OpFunctionCall %[[#Void]] %[[#Bar]] %[[#CastedFromDevice]] +; CHECK: %[[#LoadedHost:]] = OpLoad %[[#AtHost]] %[[#VarHost]] +; CHECK: %[[#CastedFromHost:]] = OpPtrCastToGeneric %[[#GenPtrChar]] %[[#LoadedHost]] +; CHECK: OpFunctionCall %[[#Void]] %[[#Bar]] %[[#CastedFromHost]] + +define spir_func void @foo() { +entry: + %device_var = alloca ptr addrspace(5) + %host_var = alloca ptr addrspace(6) + %p1 = load ptr addrspace(5), ptr %device_var + %p2 = addrspacecast ptr addrspace(5) %p1 to ptr addrspace(4) + call spir_func void @bar(ptr addrspace(4) %p2) + %p3 = load ptr addrspace(6), ptr %host_var + %p4 = addrspacecast ptr addrspace(6) %p3 to ptr addrspace(4) + call spir_func void @bar(ptr addrspace(4) %p4) + ret void +} + +define spir_func void @bar(ptr addrspace(4) %data) { +entry: + %data.addr = alloca ptr addrspace(4) + store ptr addrspace(4) %data, ptr %data.addr + ret void +}